web-dev-qa-db-ja.com

OkHttpインターセプターによるインターセプトとコールの再試行

OkHttp Interceptor内でリクエストを再試行する必要があります。たとえば、Authorizationトークンを必要とする着信要求があります。 Authorizationトークンが期限切れの場合、サーバーは403コードを含む応答を返します。この場合、新しいトークンを取得し、同じchainオブジェクトを使用して再度呼び出しを試みています。

しかし、OkHttpは例外をスローします。これは、同じchainオブジェクトを使用して2つの要求を行うことはできないことを示しています。

Java.lang.IllegalStateException: network interceptor org.app.api.modules.ApplicationApiHeaders@559da2 must call proceed() exactly once

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;
    }
}
33
Araz Abishov

.interceptors()を複数回呼び出すことが許可されている.networkInterceptors()の代わりに.proceed()を使用します。

詳細については、次を参照してください: https://github.com/square/okhttp/wiki/Interceptors

46
Jake Wharton