I'm considering to switch my app repositories to use dio for all http requests, it looks really promising!
What is the best approach to refresh a JWT token with dio? Is there an easy way to get a fresh token and repeat the request with the fresh token after it got a 401?
same issue here.
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.
@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
@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; };:octocat: From gitme Android
such method wont working properly when multiple requests enqueued.
see #590
@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; };: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.
Same problem, refresh code enter into loop of requests
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;
}
}));
Any Update?
Most helpful comment
@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::octocat: From gitme Android