onError method

  1. @override
void onError(
  1. DioError err,
  2. ErrorInterceptorHandler handler
)

The callback will be executed on error.

If you want to continue the error , call handler.next.

If you want to complete the response with some custom data directly, you can resolve a Response object with handler.resolve and other error interceptor(s) will be skipped.

If you want to complete the response with an error message directly, you can reject a DioError object with handler.reject, and other error interceptor(s) will be skipped.

Implementation

@override
void onError(DioError err, ErrorInterceptorHandler handler) async {
  final options = err.response?.requestOptions;
  final request = err.requestOptions;
  final token = await _tokenManagerProvider.manager.getToken();

  if (!isRetryable(err) || options == null || token == null) {
    handler.next(err);
    return;
  }

  try {
    if (request.headers["Authorization"] != "Bearer ${token.accessToken}") {
      // tokens were refreshed by another API request.
      print(
          "just retry ${options.path} since access token was already refreshed by another request.");

      var response = await _dio.fetch(options);
      handler.resolve(response);
      return;
    }

    _dio.lock();
    _dio.interceptors.errorLock.lock();

    final newToken = await _kauthApi.refreshAccessToken(token);
    options.headers["Authorization"] = "Bearer ${newToken.accessToken}";

    _dio.unlock();
    _dio.interceptors.errorLock.unlock();

    print("retry ${options.path} after refreshing access token.");
    var response = await _dio.fetch(options);
    handler.resolve(response);
  } catch (error) {
    if (_isTokenError(error)) {
      await _tokenManagerProvider.manager.clear();
    }
    if (error is DioError) {
      handler.reject(error);
    } else {
      handler.reject(DioError(requestOptions: options, error: error));
    }
  } finally {
    // The lock must be unlocked because errors may occur while the lock is locked.
    _dio.unlock();
    _dio.interceptors.errorLock.unlock();
  }
}