30

I'm using retrofit to make requests.

I've got following error:

java.net.ProtocolException: Too many follow-up requests: 21

The code is like below:

private OkHttpClient httpClient;
private CookieManager cookieManager;

public <S> S createCookieService(Class<S> serviceClass) {
    httpClient.interceptors().clear();
    httpClient.setCookieHandler(cookieManager);
    Retrofit.Builder builder = new Retrofit
            .Builder()
            .client(httpClient)
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create());

    Retrofit retrofit = builder.client(httpClient).build();

    return retrofit.create(serviceClass);
}

And then I'm making requests:

example:

1) login

 @POST("/login")
 Call<User> login();

2) some request:

@GET("/request")
Call<PojoPojo> getPojo();

And I'm getting this error too many follow-up requests: 21.

Please help.

Payal Sorathiya
  • 756
  • 1
  • 8
  • 23
Marcin Bortel
  • 1,190
  • 2
  • 14
  • 28

6 Answers6

24

Jake Wharton wrote:

This gets thrown (by OkHttp, not Retrofit) when there are more than 20 redirects when calling an endpoint. Usually this indicates a redirect cycle between two endpoints. Both Chrome and Firefox will also stop loading the request after this many redirects and fail the request.

You need to consult with your server team or endpoint documentation to ensure you are passing the correct data directly to the endpoint you want to call. No action for Retrofit to take here.

And rest of the thread is there: https://github.com/square/retrofit/issues/1561

Marcin Bortel
  • 1,190
  • 2
  • 14
  • 28
  • 1
    This solution might be useful if you want to reduce the number of retries : https://stackoverflow.com/questions/29456534/handling-authentication-in-okhttp – eOnOe Dec 27 '19 at 23:59
7

This also happen's when the token's header's key already exists and instead of replacing it with the new token as shown below:

response.request.newBuilder()
                .header("Authorization", token)
                .build()

you add the new token(a single key can have many values in the headers), what's common in a lot of questions is add the token like this:

response.request.newBuilder()
                .addHeader("Authorization", token)
                .build()

This will result the request failing again(401) and you'll end up in a loop.

TL;DR: The correct way of setting a new token is:

response.request.newBuilder()
                    .header("Authorization", token)
                    .build()
Umar Ahmed
  • 163
  • 1
  • 5
  • 8
5

As a workaround, it is possible to use:

new OkHttpClient.Builder()
    .followRedirects(false)
    .followSslRedirects(false)

Nice to take a look at okhttp3.internal.http.RetryAndFollowUpInterceptor class source code.

I'm using version 3.12.0 of OkHttp.

Jakub Kostka
  • 551
  • 2
  • 7
  • 20
Edson Prestes
  • 51
  • 1
  • 1
4

For me the issue was: the request url was starting with "/".
Replace url @GET("/request") with @GET("request")

  • also the base url of the api should end with "/"
  • if using an Authorization header check if you need to set the value as "Bearer " + token instead

using retrofit 2.4.0 version:

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.4.0</version>
</dependency>
Mihai Morcov
  • 193
  • 1
  • 7
0

In my case it was happening because of the cookie in header was expired. It is clear that we need to fix this in server side code but in case we can't change server side code we can use this workaround.

Following is the workaround which worked for me

catch (ProtocolException e) {
        
        Timber.w(e);
        if (e.getMessage().contains("Too many follow-up requests")) {
            doSynchronousLogin();

            Request.Builder builder = chain.request().newBuilder();
            builder.addHeader("Cookie", dataManager.getCookie());
            Timber.w("Request processed after auto-login");
            return chain.proceed(builder.build());
        }
    }

Above code is added in a retrofit interceptor

0

In okHttpClient,in the interceptor if your using authenticator, remove that authenticator. It Sets the authenticator used to respond to challenges from origin servers. It Uses [proxyAuthenticator] to set the authenticator for proxy servers.

k saran
  • 1
  • 1