Code Monkey home page Code Monkey logo

Comments (19)

wendux avatar wendux commented on May 10, 2024 37

@ToniTornado @zinwalin Have you read this example?
https://github.com/flutterchina/dio/blob/flutter/example/interceptorLock.dart , Similarly, you can repeat the request with a new dio instance after you retrieved the new token in onError, like:

  String csrfToken; //top-level variable
  dio.interceptor.response.onError = (DioError error) {
    if(error.response?.statusCode==401){
      Options options=error.response.request;
      // If the token has been updated, repeat directly.
      if(csrfToken!=options.headers["csrfToken"]){
        options.headers["csrfToken"]=csrfToken;
        //repeat
       return  dio.request(options.path,options: options);
      }
      // update token and repeat
      // Lock to block the incoming request until the token updated
      dio.interceptor.request.lock();
      dio.interceptor.response.lock();
      return tokenDio.get("/token").then((d) {
        //update csrfToken
        options.headers["csrfToken"] = csrfToken = d.data['data']['token'];
      }).whenComplete((){
        dio.interceptor.request.unlock();
        dio.interceptor.response.unlock();
      }).then((e){
       //repeat
       return dio.request(options.path,options: options);
      });
    }
    return error;
  };

:octocat: From gitme Android

from dio.

mounirmesselmeni avatar mounirmesselmeni commented on May 10, 2024 13

@vimalmistry from @mauriziopinotti solution, you just have to change

return dio.request(error.requestOptions.path, options: error.requestOptions

to

return dio.fetch(options);

This will take care of passing all details about the failed request.

from dio.

Xgamefactory avatar Xgamefactory commented on May 10, 2024 9

@ToniTornado @zinwalin Have you read this example?
https://github.com/flutterchina/dio/blob/flutter/example/interceptorLock.dart , Similarly, you can repeat the request with a new dio instance after you retrieved the new token in onError, like:

  String csrfToken; //top-level variable
  dio.interceptor.response.onError = (DioError error) {
    if(error.response?.statusCode==401){
      Options options=error.response.request;
      // If the token has been updated, repeat directly.
      if(csrfToken!=options.headers["csrfToken"]){
        options.headers["csrfToken"]=csrfToken;
        //repeat
       return  dio.request(options.path,options: options);
      }
      // update token and repeat
      // Lock to block the incoming request until the token updated
      dio.interceptor.request.lock();
      dio.interceptor.response.lock();
      return tokenDio.get("/token").then((d) {
        //update csrfToken
        options.headers["csrfToken"] = csrfToken = d.data['data']['token'];
      }).whenComplete((){
        dio.interceptor.request.unlock();
        dio.interceptor.response.unlock();
      }).then((e){
       //repeat
       return dio.request(options.path,options: options);
      });
    }
    return error;
  };

:octocat: From gitme Android

such method wont working properly when multiple requests enqueued.
see #590

from dio.

scopendo avatar scopendo commented on May 10, 2024 5

Following updating to version 4.x, I found that I needed to change my onError handler from:

Future onError(DioError err) async {
  ...
  return retryDio.request(...);
}

To the new handler signature and approach:

Future onError(DioError err, ErrorInterceptorHandler handler) async {
  ...
  try {
    final response = await retryDio.request(...);
    return handler.resolve(response);
  } on DioError catch (e) {
    return handler.reject(e);
  }
}

from dio.

mdasifcse avatar mdasifcse commented on May 10, 2024 3

from dio.

JDChi avatar JDChi commented on May 10, 2024 2

@ToniTornado @zinwalin Have you read this example?
https://github.com/flutterchina/dio/blob/flutter/example/interceptorLock.dart , Similarly, you can repeat the request with a new dio instance after you retrieved the new token in onError, like:

  String csrfToken; //top-level variable
  dio.interceptor.response.onError = (DioError error) {
    if(error.response?.statusCode==401){
      Options options=error.response.request;
      // If the token has been updated, repeat directly.
      if(csrfToken!=options.headers["csrfToken"]){
        options.headers["csrfToken"]=csrfToken;
        //repeat
       return  dio.request(options.path,options: options);
      }
      // update token and repeat
      // Lock to block the incoming request until the token updated
      dio.interceptor.request.lock();
      dio.interceptor.response.lock();
      return tokenDio.get("/token").then((d) {
        //update csrfToken
        options.headers["csrfToken"] = csrfToken = d.data['data']['token'];
      }).whenComplete((){
        dio.interceptor.request.unlock();
        dio.interceptor.response.unlock();
      }).then((e){
       //repeat
       return dio.request(options.path,options: options);
      });
    }
    return error;
  };

:octocat: From gitme Android

such method wont working properly when multiple requests enqueued.
see #590

I also met the same question . In my project , inside "onError" , dio.interceptor.errorLock.lock(); call multipletime.

from dio.

Fleximex avatar Fleximex commented on May 10, 2024 1

The following solution/hack seems to work for me. Just keep track of a number (maybe a boolean would also work). When a request is successful or when there is an error while the counter is uneven (1) set the _repeatCounter to 0 (even number).
With the status code responses of the requests you want to repeat, in my case 401, you up the counter (to 1) before retrying the request.

The code is not battle tested (what happens i.e. when you make multiple requests simultaneously?).
But it seems to work well enough.

int _repeatCounter = 0;

...

dio.interceptors.add(InterceptorsWrapper(onError: (error) async {
    if (error.response.statusCode == 401 && _repeatCounter.isEven) {
        dio.interceptors.requestLock.lock();
        dio.interceptors.responseLock.lock();
        await refreshCredentials();
        dio.interceptors.requestLock.unlock();
        dio.interceptors.responseLock.unlock();
        _repeatCounter++;
        return await dio.request(
            error.request.path,
            queryParameters: error.request.queryParameters,
            data: error.request.data,
            options: Options(method: error.request.method),
        );
    }
    _repeatCounter = 0;
    return error;
}, onResponse: (response) async {
    if (response.statusCode == 200) {
        _repeatCounter = 0;
    }
}));

from dio.

wendux avatar wendux commented on May 10, 2024 1

Please check out:
https://github.com/flutterchina/dio/blob/master/example/interceptor_lock.dart
https://github.com/flutterchina/dio/blob/master/dio/test/interceptor_test.dart

from dio.

mauriziopinotti avatar mauriziopinotti commented on May 10, 2024 1

@vimalmistry I have shared a code snippet to handle 401 errors here: #1088 (comment)

from dio.

zinwalin avatar zinwalin commented on May 10, 2024

same issue here.

from dio.

ToniTornado avatar ToniTornado commented on May 10, 2024

Another idea is to decode the JWT token in an interceptor and get it's expiry date; if it is expired or about to expire, it could be refreshed and replaced before the request continues. Sounds like a clean solution, but I haven't tried it yet. As I said, I'm still evaluating which library to use.

And I was curious to hear about experiences from others how to deal with it.

from dio.

giandifra avatar giandifra commented on May 10, 2024

Same problem, refresh code enter into loop of requests

from dio.

kadnan0900 avatar kadnan0900 commented on May 10, 2024

Any Update?

from dio.

douglasiacovelli avatar douglasiacovelli commented on May 10, 2024

I've just run into a similar issue and followed the code that was used on the test 'Interceptor error lock: test' found here: https://github.com/flutterchina/dio/blob/master/dio/test/interceptor_test.dart.

It worked flawlessly except from the fact that you must keep track of how many refreshes you have already tried. This is important so you don't get in a loop and instead just logout the user. This can be done by using a request header with a retry_count, for example.

//When retrying the original request, you can add this header
request.headers['retry_count'] = 1;

//and on the error before refreshing the accesstoken you can verify the retry_count.
if (request.headers['retry_count'] == 1) {
    //logout user
    return e;
} else {
    //refresh token
}

from dio.

mdasifcse avatar mdasifcse commented on May 10, 2024

Same problem, refresh code enter into loop of requests
you got the answer ,plz tell how to solve this

from dio.

douglasiacovelli avatar douglasiacovelli commented on May 10, 2024

I've created a gist with the retry-count example. This code is based on this test I mentioned earlier.

https://gist.github.com/douglasiacovelli/8fe98ec4a98e72bef5da1189a19fb3b9

from dio.

HasikaDilshani avatar HasikaDilshani commented on May 10, 2024

I am also getting infinite loop
any solutions?

from dio.

mauriziopinotti avatar mauriziopinotti commented on May 10, 2024

after upgrading to 4.x this no longer works, I get

error: The argument type 'RequestOptions' can't be assigned to the parameter type 'Options'.

Anyone else faced this?

Of course, you can always do:

          RequestOptions options = e.response.request;

          // ...

          return _dio.request(options.path,
              options: Options(
                method: options.method,
                sendTimeout: options.sendTimeout,
                receiveTimeout: options.receiveTimeout,
                extra: options.extra,
                headers: options.headers,
                responseType: options.responseType,
                contentType: options.contentType,
                validateStatus: options.validateStatus,
                receiveDataWhenStatusError: options.receiveDataWhenStatusError,
                followRedirects: options.followRedirects,
                maxRedirects: options.maxRedirects,
                requestEncoder: options.requestEncoder,
                responseDecoder: options.responseDecoder,
                listFormat: options.listFormat,
              ));

from dio.

vimalmistry avatar vimalmistry commented on May 10, 2024
final response = await retryDio.request(...);
    return handler.resolve(response);

Can you share details code?
Screenshot 2021-04-17 at 1 50 20 PM

In my case Shows error : Options? is not subtype of RequestOptions (errors.requestOptions)

from dio.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.