Search code examples
javahttp-redirecthttpsapache-httpclient-5.x

How to follow redirects for POST in Apache HttpClient 5.1


I'm looking how to follow redirects for POST requests as POST in Apache HttpClient 5.1

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 (Moved Temporarily) – the redirect is not automatically followed. This is specified by the HTTP RFC 2616

There are usecases, however, when POST request has to be redirected as POST. In such cases, the default behavior has to be changed in order to relax the strict HTTP specification.

With Apache HttpClient 4.5 this could be easily achieved by replacing DefaultRedirectStrategy with LaxRedirectStrategy or with your own custom implementation of RedirectStrategy interface. Examples:

In Apache HttpClient 5.1 this doesn't work anymore. The RedirectStrategy interface changed and no longer contain getRedirect method, LaxRedirectStrategy implementation has also been removed.

Is there a way to override default POST redirect behavior in Apache HttpClient 5.1 similar or as simple as in HttpClient 4.5?


Solution

  • Since no one replied so far I'll post my own findings as an answer.

    One of internal servers in my company that handled file uploads had to be converted from HTTP to HTTPS. Additional requirement was: if someone forgot to update their URLs and uploaded files using HTTP - their uploads have to be properly redirected to HTTPS and processed too.

    That was easy to do with HttpClient 4.5 (see the original question) but with HttpClient 5.1. If the clients sent POST requests over HTTP to HTTPS server - they were redirected (301 Moved Permanently), POST was converted to GET, and then rejected by the server.

    Examining the source code I found that in version 5.1 HttpClient developers decided to strictly enforce HTTP RFC 2616 and removed the very possibility to override or relax the redirect strategy.

    In HttpClient 5.1.x request redirection is handled by RedirectExec class, where the logic of replacing POST with GET for certain status codes (302, 302, 303) is hardcoded:

    enter image description here

    That made client side solution rather cumbersome and expensive. However, since I had full control over the server I decided to fix the problem on the server side.

    It was done by reconfiguring the NGNIX server to return "308 Permanent Redirect" on HTTP to HTTPS redirects, instead of default "301 Moved Permanently"

    server {
        listen 80      default_server;
        listen [::]:80 default_server;
        server_name _;
        return 308 https://$host$request_uri;
    }
    

    Not exactly the solution I was hoping for, but works great for my use case, and is much simpler than writing a custom implementation of RedirectExec