通过OkHttp拦截器进行拦截并重试调用 [英] Intercept and retry call by means of OkHttp Interceptors
问题描述
我需要在OkHttp Interceptor
内部重试请求.例如,存在需要Authorization
令牌的传入请求.如果Authorization
令牌已过期,则服务器将返回带有403
代码的响应.在这种情况下,我要获取一个新令牌并尝试使用相同的chain
对象再次进行呼叫.
I need to retry request inside of OkHttp Interceptor
. For example there is incoming request which needs Authorization
token. If Authorization
token is expired, server returns response with 403
code. In this case I am retrieving a new token and trying to make call again by using the same chain
object.
但是OkHttp抛出一个异常,该异常指出您无法使用相同的chain
对象发出两个请求.
But OkHttp throws an exception, which states that you cannot make two requests with the same chain
object.
java.lang.IllegalStateException: network interceptor org.app.api.modules.ApplicationApiHeaders@559da2 must call proceed() exactly once
我想知道在OkHttp Interceptor
内部重试网络请求的问题是否存在一种干净的解决方案?
I wonder if there is a clean solution to this problem of retrying network request inside of OkHttp Interceptor
?
public final class ApplicationApiHeaders implements Interceptor {
private static final String AUTHORIZATION = "Authorization";
private TokenProvider mProvider;
public ApplicationApiHeaders(TokenProvider provider) {
mProvider = provider;
}
@Override
public Response intercept(Chain chain) throws IOException {
Token token = mProvider.getApplicationToken();
String bearerToken = "Bearer " + token.getAccessToken();
System.out.println("Token: " + bearerToken);
Request request = chain.request();
request = request.newBuilder()
.addHeader(AUTHORIZATION, bearerToken)
.build();
Response response = chain.proceed(request);
if (!response.isSuccessful() && isForbidden(response.code())) {
Token freshToken = mProvider.invalidateAppTokenAndGetNew();
String freshBearerToken = freshToken.getAccessToken();
Request newRequest = chain.request();
newRequest = newRequest.newBuilder()
.addHeader(AUTHORIZATION, freshBearerToken)
.build();
response = chain.proceed(newRequest);
}
return response;
}
private static boolean isForbidden(int code) {
return code == HttpURLConnection.HTTP_FORBIDDEN;
}
}
推荐答案
使用.interceptors()
代替.networkInterceptors()
,允许多次调用.proceed()
.
Use .interceptors()
instead of .networkInterceptors()
which are allowed to call .proceed()
more than once.
有关更多信息,请参见: https://square.github.io/okhttp/interceptors/
For more information see: https://square.github.io/okhttp/interceptors/
这篇关于通过OkHttp拦截器进行拦截并重试调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!