Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QueuedInterceptorWrapper does not trigger on error, but InterceptorsWrapper does. #1683

Closed
CodeFoxLk opened this issue Feb 21, 2023 · 7 comments
Labels
i: wontfix This will not be worked on

Comments

@CodeFoxLk
Copy link

CodeFoxLk commented Feb 21, 2023

Package

dio

Version

5.0.0

Output of flutter doctor -v

Dart Version

No response

Steps to Reproduce

QueuedInterceptorWrapper does not trigger an error, but InterceptorsWrapper does.

This is my code to get a refresh token. The problem is when the refresh token response returns an error status of [403]. the error function not triggering. and not execute codes under the [
_dio.post(URLEndPoints.refreshTokenRequest
] post request

but when I use InterceptorsWrapper. it working fine. 

_dio.interceptors.add(QueuedInterceptorsWrapper(
      onRequest: (options, handler) async {
        final accessToken = await _jwtHandler.getAccessToken();
        if (accessToken != null) {
          // if access token is available
          options.headers['Authorization'] = 'Bearer $accessToken';
        }
        return handler.next(options);
      },
      onResponse: (response, handler) {
        handler.next(response);
      },
      onError: (DioError error, handler) async {
        if (error.response?.statusCode == StatusCode.UNAUTHORIZED) {
          try {
            final Tokens? newTokens = await refreshTokens();

            if (newTokens != null) {
              await _jwtHandler.saveJWT(accessToken: newTokens.accessToken, refreshToken: newTokens.refreshToken);
              AppLogger.logInfo(newTokens.toString());
              //Complete the request with Response object and other error interceptor(s) will not be executed. This will be considered a successful request!
              //handler.resolve() means the error is resolved and stops the other er ror interceptors.
              return handler.resolve(await _retry(error.requestOptions));
            } else {
              //delete remains tokens
              await _netErrorHandler.deleteTokensAndNavigateToAuth();
              return handler.reject(error);
            }
          } on DioError catch (e) {
            AppLogger.logError('AuthInterceptor - Error when retrying with a new Refresh');

            if (e.response?.statusCode == StatusCode.UNAUTHORIZED) {
              AppLogger.logError('AuthInterceptor - Error 401 retrying with a new Refresh');
            }
            rethrow;
          } catch (e) {
            AppLogger.logError('Error during retry - $e');
            rethrow;
          }

          //when 403
        } else if (error.response?.statusCode == StatusCode.FORBIDDEN) {
          await _netErrorHandler.deleteTokensAndNavigateToAuth();
        }

        handler.next(error);
      },
    ));

Future<Tokens?> refreshTokens() async {
    final refreshToken = await _jwtHandler.getRefreshToken();
   
    if (refreshToken == null) {
      return null;
    }
    final response = await _dio.post<String>(URLEndPoints.refreshTokenRequest,
        data: {'token': refreshToken},
        options: Options(headers: {'Content-Type': 'application/json'}));

    if (response.statusCode == StatusCode.OK && response.data != null) {
      AppLogger.logInfo(response.data!);
      final tokens = Tokens.tokenModelFromJson(response.data!);

      return tokens;
    } else {
      //refresh token is invalid
      AppLogger.logError('refresh token not received');
      return null;
    }
  }

Expected Result

trigger onError function after get 403. from [ _dio.post(URLEndPoints.refreshTokenRequest........]

Actual Result

does not trigger onError function after get 403. from [ _dio.post(URLEndPoints.refreshTokenRequest........]

@CodeFoxLk CodeFoxLk added h: need triage This issue needs to be categorized s: bug Something isn't working labels Feb 21, 2023
@ueman
Copy link
Contributor

ueman commented Feb 22, 2023

Hey, thanks for the report. Are you willing to submit a fix in a PR?

If not, can you provide an executable example which exhibits the bug?

@llfbandit
Copy link

The issue is related to QueuedInterceptorsWrapper or QueuedInterceptor where you make other requests inside.

Since this kind of interceptor provides a sequential processing of each event, when you make a request returning an invalid status the onError event is not triggered while you are in the currently running scope, the response is considered in "pending state" regarding the queue.

@CodeFoxLk
Copy link
Author

@llfbandit How do I manually change that pending state? Is there a way to do it?

@llfbandit
Copy link

You must use another client without your jwt interceptor. Use it also for your retry request otherwise you will be in the same situation in case of unsuccessful request.

@AlexV525
Copy link
Member

From your code, we don't know what's happening with your handler*, but as @llfbandit suggested, a new Dio client should be used inside the token refresh request. See the example for more details.

@AlexV525 AlexV525 closed this as not planned Won't fix, can't repro, duplicate, stale Mar 12, 2023
@AlexV525 AlexV525 added i: wontfix This will not be worked on and removed h: need triage This issue needs to be categorized s: bug Something isn't working labels Mar 12, 2023
@farmanteachedison
Copy link

hi, @CodeFoxLk have you found the answer?

@rashmisridar
Copy link

Hi @CodeFoxLk @AlexV525 any update on this. In the latest version getting the same issue #2335

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
i: wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

6 participants