45

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.

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

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;
    }
}
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Araz Abishov
  • 1,661
  • 3
  • 15
  • 26

1 Answers1

67

Use .interceptors() instead of .networkInterceptors() which are allowed to call .proceed() more than once.

For more information see: https://square.github.io/okhttp/interceptors/

Pablo Johnson
  • 1,044
  • 15
  • 21
Jake Wharton
  • 75,598
  • 23
  • 223
  • 230