简体   繁体   中英

Apache HttpComponents ignoring POST data on redirect (HTTP 302)

I'm using Apache HttpComponents to connect to another company API's.

This company server is redirecting my POST request to another location, so I had to configure HttpComponents to allow circular redirects:

private RequestConfig defaultRequestConfig = RequestConfig.custom()
    .setCookieSpec(CookieSpecs.DEFAULT)
    .setCircularRedirectsAllowed(true)
    .build();

private CloseableHttpClient httpclient = HttpClients.custom()
    .setDefaultRequestConfig(defaultRequestConfig)
    .setRedirectStrategy(CustomRedirectStrategy.INSTANCE)
    .build();

GET requests are working fine, but when I try to POST, it seems that HttpComponents is ignoring the body I'm trying to send. Bellow is the code I'm using to POST and also the (resumed) log generated by HttpComponents:

public CloseableHttpResponse doPOST(String url, String stringEntity) throws IOException {
    HttpPost request = new HttpPost(url);
    request.setEntity(new StringEntity(stringEntity));
    request.setHeader("Accept", "application/json;");
    request.setHeader("Content-type", "application/json;");
    return httpclient.execute(request);
}

-> POST (http://some-server.com/api/test)       (Content-Length: 65)
<-  302 (https://some-server.com/api/test)

-> POST (https://some-server.com/api/test)      (Content-Length: 0)
<-  302 (http://some-server.com/api/test)

-> POST (http://some-server.com/api/test)       (Content-Length: 0)
<-  302 (https://some-server.com/api/test)

-> POST (https://some-server.com/api/test)      (Content-Length: 0)
<-  404 (Not Found)

-> are for messages I've sent, and <- are for messages received

I see that the first POST has a Content-Length of 65, but POST's following the redirection doesn't.

Is HttpComponents ignoring my POST entity after redirection? If so, how can I configure it to send this data even on redirections?

Obs.: CustomRedirectStrategy is a class I've created, which extends from LaxRedirectStrategy and overrides #getRedirect to redirect POST methods to POST, not GET.

To repost the data from the original POST to the redirections, we can implement a specific redirect strategy, overriding #getRedirect :

@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class CustomRedirectStrategy extends LaxRedirectStrategy {

    public static final CustomRedirectStrategy INSTANCE = new CustomRedirectStrategy();

    @Override
    public HttpUriRequest getRedirect(
            final HttpRequest request,
            final HttpResponse response,
            final HttpContext context) throws ProtocolException {
        final URI uri = getLocationURI(request, response, context);
        final String method = request.getRequestLine().getMethod();
        if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
            return new HttpHead(uri);
        } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
            return new HttpGet(uri);
        } else if (method.equalsIgnoreCase(HttpPost.METHOD_NAME)) {
            return RequestBuilder.copy(request).setUri(uri).build(); // Here
        } else {
            final int status = response.getStatusLine().getStatusCode();
            if (status == HttpStatus.SC_TEMPORARY_REDIRECT) {
                return RequestBuilder.copy(request).setUri(uri).build();
            } else {
                return new HttpGet(uri);
            }
        }
    }

}

For the POST method, return a request based on the original request.

For this to work you have to set this redirect strategy on the HttpClient instance:

public CloseableHttpClient getHttpClient() {
    return HttpClients.custom()
            .setDefaultRequestConfig(defaultRequestConfig)
            .setRedirectStrategy(CustomRedirectStrategy.INSTANCE) // Here
            .build();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM