Closed logblythe closed 3 years ago
Issue-Label Bot is automatically applying the label question
to this issue, with a confidence of 0.67. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!
Links: app homepage, dashboard and code for this bot.
Sorry it took me so long to reply, are you trying to retry onResponse or onError? Also how does your interceptor look like? It should work in the way you are trying to do it, so it might be a bug depending on how it's implemented.
@CodingAleCR , this is my implementation of the retry interceptor. I am making this post request in which I get the token from FlutterSecureStorage package.
Future<dynamic> post(String url, {Map<String, dynamic> params}) async {
var storage = FlutterSecureStorage();
var _headers = {"token": await storage.read(key: KEY_TOKEN)};
print('the params $params');
var responseJson;
try {
final response = await client.post(
_baseUrl + url,
headers: _headers,
body: params,
);
responseJson = _returnResponse(response);
} on SocketException {
throw FetchDataException({"message": 'No Internet connection'});
}
return responseJson;
}
In my RetryPolicyClass
class ExpiredTokenRetryPolicy extends RetryPolicy {
@override
Future<bool> shouldAttemptRetryOnResponse(ResponseData response) async {
if (response.statusCode == 401) {
//perform token refresh,get the new token and update it in the secure storage
var storage = FlutterSecureStorage();
await storage.write(key: KEY_TOKEN, value: updatedToken);
return true;
}
return false;
}
}
Now, when the post request is retried after updating the token in the secured storage, same old token is being used. How can I use the updated token when the request is retried.
And how is your interceptor looking? Are you using Client with Interceptor o just Http with Interceptor?
@CodingAleCR Apologies for the late reply. I am just logging with the interceptor.
class LoggingInterceptor implements InterceptorContract {
@override
Future<RequestData> interceptRequest({RequestData data}) async {
print(data);
return data;
}
@override
Future<ResponseData> interceptResponse({ResponseData data}) async {
print(data);
return data;
}
}
and using it like client
final client = HttpClientWithInterceptor.build(
retryPolicy: ExpiredTokenRetryPolicy(),
interceptors: [LoggingInterceptor()],
);
No worries @logblythe ! In order for the request to be properly updated I would suggest you create an additional interceptor to include the token in your headers.
Here's what's happening right now:
Notice that between steps 3 and 4, at no point the request is updated since the header in the request is static.
To solve this you could use an interceptor, it would make the token in header respond better to changes in storage, for example something like this:
class AuthorizationInterceptor implements InterceptorContract {
@override
Future<RequestData> interceptRequest({RequestData data}) async {
data.headers["token"] = await storage.read(key: YOUR_KEY);
return data;
}
@override
Future<ResponseData> interceptResponse({ResponseData data}) async {
return data;
}
}
When the retry happens, the updated token doesn't get used. If I make the request again, then only the updated token is being used.
Yes, thst is because the retry policy updates the storage but the request is still the same as before. The solution would be to use an interceptor to attach the header you need like described above in my previous message.
I tried using another interceptor as you suggested, but even that interceptor doesn't use the updated value.
Do you have an example repository that maybe I could take a look, I ask this because I'm doing the exact same thing as you are in my projects but it's working fine for some reason, so I want to figure out what's happening and help you in a better way. I'm also down for a Gitduck session or something like that if you feel more comfortable with it.
I am not very familiar with the pair programming tools. I tried sharing with Gitduck but it didn't go well. However we can still go with CodeTogether. Let me know what time works for you.
No worries @logblythe ! In order for the request to be properly updated I would suggest you create an additional interceptor to include the token in your headers.
Here's what's happening right now:
- You make the request with manually set header.
- Request fails because the token has expired.
- Retry policy is checked and updates the token in storage.
- Request is retried.
- Request fails.
Notice that between steps 3 and 4, at no point the request is updated since the header in the request is static.
To solve this you could use an interceptor, it would make the token in header respond better to changes in storage, for example something like this:
class AuthorizationInterceptor implements InterceptorContract { @override Future<RequestData> interceptRequest({RequestData data}) async { data.headers["token"] = await storage.read(key: YOUR_KEY); return data; } @override Future<ResponseData> interceptResponse({ResponseData data}) async { return data; } }
I was finally able to use the updated token, via another interceptor. Thanks a lot for helping me out.
That sounds great, I was just about to reply with a time window for the call. I'm glad to hear it worked out.
@logblythe hey, how did you solve this problem eventually?
I have been using http and http_interceptor for networking in the flutter application. In the request, I am adding token header from the SecureStorage. Now once the token expires(401 error), I refresh the token, update the token in SecureStorage. But when the request gets repeated old token is used instead of the new one