HttpClient 4 – Follow Redirects for POST

1. Overview

This quick tutorial will show how to configure the Apache HttpClient 4 to automatically follow redirects for POST requests.

If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.

By default, only GET requests resulting in a redirect are automatically followed. If a POST requests is answered with either HTTP 301 Moved Permanently or with 302 Found – the redirect is not automatically followed.

This is specified by the HTTP RFC 2616:

If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

There are of course usecases where we need to change that behavior and relax the strict HTTP specification.

First, let’s check the default behavior:

@Test
public void givenPostRequest_whenConsumingUrlWhichRedirects_thenNotRedirected() 
  throws ClientProtocolException, IOException {
    HttpClient instance = HttpClientBuilder.create().build();
    HttpResponse response = instance.execute(new HttpPost("http://t.co/I5YYd9tddw"));
    assertThat(response.getStatusLine().getStatusCode(), equalTo(301));
}

As you can see, the redirect is not followed by default, and we get back the 301 Status Code.

2. Redirecting on HTTP POST

2.1. For HttpClient 4.3 and After

In HttpClient 4.3, a higher level API has been introduced for both creation and configuration of the client:

@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected() 
  throws ClientProtocolException, IOException {
    HttpClient instance = 
      HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
    HttpResponse response = instance.execute(new HttpPost("http://t.co/I5YYd9tddw"));
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

Notice the HttpClientBuilder is now the starting point of a fluent API which allows full configuration of the client in a more readable way than before.

2.2. For HttpClient 4.2

In the previous version of HttpClient (4.2) we can configure the redirect strategy directly on the client:

@SuppressWarnings("deprecation")
@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected() 
  throws ClientProtocolException, IOException {
    DefaultHttpClient client = new DefaultHttpClient();
    client.setRedirectStrategy(new LaxRedirectStrategy());

    HttpResponse response = client.execute(new HttpPost("http://t.co/I5YYd9tddw"));
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

Notice that now, with the new LaxRedirectStrategy, the HTTP Restrictions are relaxed and the redirect is followed over POST as well – leading to a 200 OK status code.

2.3. Pre HttpClient 4.2

Before HttpClient 4.2, the LaxRedirectStrategy class didn’t exist, so we need to roll our own:

@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected() 
  throws ClientProtocolException, IOException {
    DefaultHttpClient client = new DefaultHttpClient();
    client.setRedirectStrategy(new DefaultRedirectStrategy() {
        /** Redirectable methods. */
        private String[] REDIRECT_METHODS = new String[] { 
            HttpGet.METHOD_NAME, HttpPost.METHOD_NAME, HttpHead.METHOD_NAME 
        };

        @Override
        protected boolean isRedirectable(String method) {
            for (String m : REDIRECT_METHODS) {
                if (m.equalsIgnoreCase(method)) {
                    return true;
                }
            }
            return false;
        }
    });

    HttpResponse response = client.execute(new HttpPost("http://t.co/I5YYd9tddw"));
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

3. Conclusion

This quick guide illustrated how to configure any version of the Apache HttpClient 4 to follow redirects for HTTP POST requests as well – relaxing the strict HTTP standard.

The implementation of all these examples and code snippets can be found in my github project – this is an Eclipse based project, so it should be easy to import and run as it is.

Related posts:

Apache Commons Collections BidiMap
Java Program to Implement Fisher-Yates Algorithm for Array Shuffling
Java Program to Implement Gauss Jordan Elimination
A Guide to Queries in Spring Data MongoDB
Auditing with JPA, Hibernate, and Spring Data JPA
Compare Two JSON Objects with Jackson
Lập trình đa luồng với CompletableFuture trong Java 8
Java Program to Implement Hash Tables with Linear Probing
Lớp HashMap trong Java
Chuyển đổi giữa các kiểu dữ liệu trong Java
OAuth2 for a Spring REST API – Handle the Refresh Token in AngularJS
Spring Security Remember Me
Java Program to Implement Affine Cipher
How to Set TLS Version in Apache HttpClient
HttpClient Basic Authentication
Java Program to Check Whether a Given Point is in a Given Polygon
Java Program to Encode a Message Using Playfair Cipher
Java Program to Check Whether a Directed Graph Contains a Eulerian Path
Migrating from JUnit 4 to JUnit 5
Hướng dẫn sử dụng String Format trong Java
Java Program to Implement Find all Forward Edges in a Graph
Java Convenience Factory Methods for Collections
Jackson Ignore Properties on Marshalling
Cài đặt và sử dụng Swagger UI
Spring MVC Setup with Kotlin
Java Program to Implement Heap’s Algorithm for Permutation of N Numbers
Converting between an Array and a List in Java
Java Program to Check if a Directed Graph is a Tree or Not Using DFS
Spring Boot - Building RESTful Web Services
Java Program to Check if any Graph is Possible to be Constructed for a Given Degree Sequence
Working with Network Interfaces in Java
RestTemplate Post Request with JSON