web-dev-qa-db-fra.com

Intercepter et réessayer l'appel au moyen d'intercepteurs OkHttp

Je dois réessayer la demande à l'intérieur de OkHttp Interceptor. Par exemple, il existe une demande entrante qui nécessite un jeton Authorization. Si le jeton Authorization a expiré, le serveur renvoie une réponse avec 403 code. Dans ce cas, je récupère un nouveau jeton et j'essaie de faire un nouvel appel en utilisant le même objet chain.

Mais OkHttp lève une exception, qui indique que vous ne pouvez pas faire deux demandes avec le même objet chain.

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

Je me demande s'il existe une solution propre à ce problème de nouvelle tentative de requête réseau à l'intérieur de 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

Utilisez .interceptors() au lieu de .networkInterceptors() qui sont autorisés à appeler .proceed() plus d'une fois.

Pour plus d'informations, voir: https://github.com/square/okhttp/wiki/Interceptors

46
Jake Wharton