Comments (19)
@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;
};
from dio.
@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.
@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 inonError
, 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; };
such method wont working properly when multiple requests enqueued.
see #590
from dio.
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.
from dio.
@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 inonError
, 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; };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.
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.
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.
@vimalmistry I have shared a code snippet to handle 401 errors here: #1088 (comment)
from dio.
same issue here.
from dio.
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.
Same problem, refresh code enter into loop of requests
from dio.
Any Update?
from dio.
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.
Same problem, refresh code enter into loop of requests
you got the answer ,plz tell how to solve this
from dio.
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.
I am also getting infinite loop
any solutions?
from dio.
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.
final response = await retryDio.request(...); return handler.resolve(response);
In my case Shows error : Options? is not subtype of RequestOptions (errors.requestOptions)
from dio.
Related Issues (20)
- Memory issue when sharing CancelToken between posts for IO implementation HOT 2
- The getter 'requestLock' isn't defined for the type 'Interceptors'. HOT 1
- How can I avoid the cooking value to expanded on each retry? HOT 1
- Cannot add values to dio data inside interceptor HOT 1
- Bad state: Cannot add event after closing HOT 2
- Error: Exception in Java code called through JNI: java.lang.RuntimeException: All available Cronet providers are disabled. A provider should be enabled before it can be used. HOT 1
- socketexception: connection reset by peer (os error: connection reset by peer, errno = 104), address = xxxxx HOT 1
- Dio cannot resolve hostname http://127.0.0.1.lambdatest:port HOT 7
- Unexpected Behavior with ErrorInterceptor Not Catching DioException on Retried Requests HOT 19
- 科学计数法转换问题 java接口返回double=1.05555046E9 在dart中 用double接收后值不对 HOT 1
- class Response<T> .toString() probably should contain whole class fields HOT 1
- request.uri have a different query parameter order than response.realUri and response.requestOptions.uri HOT 7
- A suggestion regarding the compose method in RequestOptions. HOT 5
- Flutter web - simple request causing OPTIONS request HOT 4
- 'package:dio/src/options.dart': Failed assertion: line 102 pos 12: 'value.isEmpty || kIsWeb || Uri.parse(value).host.isNotEmpty': is not true. HOT 1
- Add a response time to the response result HOT 4
- Support flutter web for native_dio_adapter HOT 6
- DioException HttpException: Connection closed before response was received HOT 2
- A request with an interceptor, which produces an error, makes the code stuck. HOT 1
- Update Interceptor return types for 6.0.0
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dio.