我正在构建一个Android应用程序,它将从REST API中获取数据。
对于我的所有请求,我添加了一个RequestInterceptor,它将为我的所有请求添加一个标头(Authorization)。 在RequestInterceptor中,我正在调用当前access_token的方法,然后将标头填充到请求中。
RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
Token token = TokenPreferences.getToken();
request.addHeader("Authorization", token.getTokenType() + " " + token.getAccessToken());
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://example.com")
.setRequestInterceptor(requestInterceptor)
.build();
...
这在access_token过期之前一直正常,然后请求将失败,HTTP状态为401 Unauthorized。 发生这种情况时,我想提出一个新的请求,从我获得的refresh_token中获取一个新的access_token,然后再次执行第一个请求。
我不确定如何做到这一点。
答案 0 :(得分:1)
尝试com.squareup.okhttp.Authenticator
。据我所知,这比com.squareup.okhttp.Interceptor
(你可以在其他地方找到的建议)更可取,因为它只会引发未经授权的请求。这是一个基本的例子:
public class ApiAuthenticator implements Authenticator {
@Override
public Request authenticate(Proxy proxy, Response response) throws IOException {
for (Challenge challenge : response.challenges()) {
if (challenge.getScheme().equals("Bearer")) {
String authToken = // Refresh the token here
if (authToken != null) {
return response.request().newBuilder()
.header("Authorization", "Bearer " + authToken)
.build();
}
}
}
return null;
}
@Override
public Request authenticateProxy(Proxy proxy, Response response) throws IOException {
return null;
}
}
您可以将其附加到您的客户端,如下所示:
okHttpClient.setAuthenticator(new ApiAuthenticator());
请注意,如果您使用Retrofit刷新令牌并且令牌无效,则可能会遇到403代码的意外,难以调试的行为,但解决方案只是使用try / catch块。
try {
token = oauthService.refreshAccessToken(args);
} catch (RetrofitError error) {
// Do something that leads to login
}
答案 1 :(得分:0)
Retrofit中未实现重试机制。它将在v2中。 (Retrying requests manually)
您应该通过onFailure()回调的递归调用实现重试Deepack suggested。
答案 2 :(得分:0)
我遇到了同样的问题,目前我还不知道如果因未经授权的错误导致请求失败,请重试我的请求。
虽然 @Yuriy Ashaev 提到重试机制应该是v2.0 Retrofit版本的一部分,但这应该仅用于5xx错误(请参阅Request Object draft description here)并尝试重试由于其他原因而失败的请求将引发异常。
截至目前,您仍然可以将自己的ErrorHandler添加到RestAdapter并捕获Unauthorized错误以获取刷新令牌。以下是实现此目的的方法:
class RestErrorHandler implements retrofit.ErrorHandler {
@Override
public Throwable handleError(RetrofitError cause) {
Response r = cause.getResponse();
if (r != null && r.getStatus() == 401) {
Token token = mTokenProvider.fetchToken();
if (token != null) {
addHeader(HEADER_AUTHORIZATION, token.getToken_type() + " " + token.getAccess_token());
}
// Todo: Relaunch previous request
return cause;
}
return cause;
}
}
但是,除了在您的ErrorHandler中返回RetrofitError时将调用的所有 failure()请求回调中,我还没有看到从此点重试失败请求的任何方法。 ..
如果有人能指出我们如何从ErrorHandler重试失败的请求,我真的很感激,因为响应只指向f-请求网址。