Dio Interceptors in flutter example – how to make App interceptor in Flutter Appliction

Getting data from Database is simple but for some simple apps sometimes we need to send some data in the header section in every API call. For Example, Sending JWT (JSON Web tokens) for authentication of the API call. To Get this we create Dio Interceptor and in this article, we will cover Dio interceptors in a flutter example.

Dio is the library to make API calls and it gives us the functionality to make Interceptor Dio in Pub.dev

In-App Interceptor we also handle the Errors and response. All of them we will cover with the example code.

Creating the App Interceptor Class

we will begin with creating an app interceptor class in our App.

class AppInterceptor {

}

First, we will initialize the Dio object in our Class. And Static BaseUrl variable

class AppInterceptor {
  var dio = Dio();
  static String baseUrl = "========URL=========";
}

Next, Add the class, Constructor AppInterceptor(). And first, we will add the baseOptions into the Constructor which will take baseUrl and ContentType for an API call.

AppInterceptor() {
 dio.options = BaseOptions(contentType: 'application/json', baseUrl: baseUrl);
}

Now is the time when we add the dio interceptors below the basicOptions. Use the add function to get the functionality of the interceptor and in the add function pass InterceptorsWrapper(). This will provide onRequest, onError, onResponse callbacks

 dio.interceptors.add(InterceptorsWrapper(
        onRequest: (RequestOptions requestOptions, RequestInterceptorHandler handler) {},
        onResponse: (Response response) => responseInterceptor(response),
        onError: (DioError err, ErrorInterceptorHandler handler) {},
));

In onRequest Call Back add the code which will add the access token to every call we made using interceptor.

    onRequest: (RequestOptions requestOptions, RequestInterceptorHandler handler) {
          requestOptions.headers.putIfAbsent(
              'Authorization', () => 'Bearer ${SessionManager.getAccessToken()}');
          handler.next(requestOptions);
        },

onError is the call back that will check the expiration of the access token and will help us to generate the new access token with the help of the refresh token. In this call back we will add some conditions to detect the authentication and return us a new token depending upon the condition.

onError: (DioError err, ErrorInterceptorHandler handler) async {
  bool check = SessionManager.isLoginBool();
  if (err.response?.statusCode == 401) {
    dio.interceptors.requestLock.lock();
    dio.interceptors.responseLock.lock();
    if (SessionManager.getRefreshToken() != "") {
      Response<dynamic> response = await HttpHelper.refreshAccessToken(SessionManager.getRefreshToken());
      if (response.statusCode == 200) {
        print("New Token Received: ${response.data}");
        await SessionManager.setToken(
            response.data["access_token"],
            response.data["refresh_token"]
        );
        dio.interceptors.requestLock.unlock();
        dio.interceptors.responseLock.unlock();
        RequestOptions options = err.requestOptions;
        try{
          var resp = await dio.request(err.requestOptions.path,
              data: options.data,
              cancelToken: options.cancelToken,
              onReceiveProgress: options.onReceiveProgress,
              onSendProgress: options.onSendProgress,
              queryParameters: options.queryParameters);
          handler.resolve(resp);
        }on DioError catch (error) {
          handler.reject(error);
        }
      } else {
        print("Error refreshing token: ${response.statusCode}");
        dio.interceptors.requestLock.unlock();
        dio.interceptors.responseLock.unlock();
        handler.reject(err);
      }
    } else {
      handler.reject(err);
    }
  } else
    handler.reject(err);
}

This Above code Will handle the auth part fully. Even if the Refresh Toicken is expired then it will log out the user and let the user log in again to create the new token again for the further retained session.

In this Above Code:

SessionManager – is where we store the data in key/value pair in Shared pref/ AppStorage.

(https://pub.dev/packages/shared_preferences)

  static setToken(String accessToken, String refreshToken)  async {
    await AppStorage.store.setString(_accessTokenKey!, accessToken);
    await AppStorage.store.setString(_refreshTokenKey!, refreshToken);
  }

HttpHelper – this is the class that handles API calls Container URIs, the Function of getting data from DB, and more

  static Future<Response> refreshAccessToken(String refreshToken) {
    return _client.post(
      '$baseUrlAuth/oauth/token',
      data: FormData.fromMap({
        'refresh_token': refreshToken,
        'grant_type': 'refresh_token',
      }),
      options: Options(
        headers: {'Authorization': 'Basic YWNtZTphY21lc2VjcmV0'},
      ),
    );
  }

Full Code:

Dio interceptors in flutter example Code

import 'package:dio/dio.dart';
import 'SessionManager.dart';
import 'httpHelper.dart';

class AppInterceptor {
  var dio = Dio();
  static String baseUrl = "https://dapi.carvia.tech/finch-service";

  AppInterceptor() {
    dio.options = BaseOptions(contentType: 'application/json', baseUrl: baseUrl);

    dio.interceptors.add(InterceptorsWrapper(
        onRequest: (RequestOptions requestOptions, RequestInterceptorHandler handler) {
          requestOptions.headers.putIfAbsent(
              'Authorization', () => 'Bearer ${SessionManager.getAccessToken()}');
          handler.next(requestOptions);
        },
        onError: (DioError err, ErrorInterceptorHandler handler) async {
          bool check = SessionManager.isLoginBool();
          if (err.response?.statusCode == 401) {
            print("Refreshing Token");
            dio.interceptors.requestLock.lock();
            dio.interceptors.responseLock.lock();
            if (SessionManager.getRefreshToken() != "") {
              Response<dynamic> response = await HttpHelper.refreshAccessToken(SessionManager.getRefreshToken());
              if (response.statusCode == 200) {
                print("New Token Received: ${response.data}");
                await SessionManager.setToken(
                    response.data["access_token"],
                    response.data["refresh_token"]
                );
                dio.interceptors.requestLock.unlock();
                dio.interceptors.responseLock.unlock();
                RequestOptions options = err.requestOptions;
                try{
                  var resp = await dio.request(err.requestOptions.path,
                      data: options.data,
                      cancelToken: options.cancelToken,
                      onReceiveProgress: options.onReceiveProgress,
                      onSendProgress: options.onSendProgress,
                      queryParameters: options.queryParameters);
                  handler.resolve(resp);
                }on DioError catch (error) {
                  handler.reject(error);
                }
              } else {
                print("Error refreshing token: ${response.statusCode}");
                dio.interceptors.requestLock.unlock();
                dio.interceptors.responseLock.unlock();
                handler.reject(err);
              }
            } else {
              handler.reject(err);
            }
          } else
            handler.reject(err);
        }));
  
  }
}

For more Flutter tutorials, Tips, Tricks, Free code, Questions, and Error Solving.

Remember FlutterDecode.com

Leave a Comment