Httpclient 4, Error 302. How to Redirect

Httpclient 4, error 302. How to redirect?

For 4.1 version:

DefaultHttpClient  httpclient = new DefaultHttpClient();
httpclient.setRedirectStrategy(new DefaultRedirectStrategy() {
public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) {
boolean isRedirect=false;
try {
isRedirect = super.isRedirected(request, response, context);
} catch (ProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!isRedirect) {
int responseCode = response.getStatusLine().getStatusCode();
if (responseCode == 301 || responseCode == 302) {
return true;
}
}
return isRedirect;
}
});

Trying to Redirect. 302 Error. HTTP CLIENT 4.1.1

I think it's quite simple: you're missing HttpContext in your import statement at the top of this code block. Add org.apache.http.protocol.HttpContext somewhere in the comma-separated import list.

As for whether this is the right way to do it, what's it? Can you say more about your application?

Apache httpclient 4.x 302 redirects with keepalive off?

The problem is this part

2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << HTTP/1.1 302 Moved Temporarily
2015/04/08 15:57:25:700 EDT [DEBUG] headers - http-outgoing-0 << Content-Length: 0
2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Location: http://10.104.107.22:1354/video/Manifest?sessionID=162729772390321694625639849465722594850
2015/04/08 15:57:25:701 EDT [DEBUG] headers - http-outgoing-0 << Date: Wed, 08 Apr 2015 19:57:25 GMT

The redirect response sent back by the server does not contain any clues that the server intends to close the connection afterwards. HttpClient dutifully returns the connection back to the pool alive and gets it back to handle the redirect leading to an I/O error.

Is there really a good reason to completely disable connection persistence? I think you might be better off letting HttpClient re-use connections for the same session and then immediately evicting all persistent connections from the connection pool once the session is over.

From Oleg Kalnichevski in the follow-up comments.

HttpClient expects the opposite endpoint to explicitly state its intent and send 'Connection: close' if it intends to drop the connection.

This fixed my problem.

How to handle 302 redirection in java

I had been taking the token and closing the session and reopening the session which caused the invalidation of the token and redirection

Apache HttpClient 4.5 redirect POST request to GET request

I had the same issue I solved it by using using LaxRedirectStrategy with overridden getRedirect method.

Apparently the default behaviour for POST requests is to make the redirected call as a GET request when the initial redirect response is different than 307 or 308.

See:
DefaultRedirectStrategy which LaxRedirectStrategy inherits from.

In my case the redirect response code was a 302.

So if you want something different, you can just override the getRedirect method and provide your own implementation.

Something like:

new LaxRedirectStrategy() {
@Override
public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, 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 {
final int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_TEMPORARY_REDIRECT || status == HttpStatus.SC_MOVED_TEMPORARILY) { //HttpStatus.SC_MOVED_TEMPORARILY == 302
return RequestBuilder.copy(request).setUri(uri).build();
} else {
return new HttpGet(uri);
}
}
}
}

HttpClient 4 - how to capture last redirect URL

That would be the current URL, which you can get by calling

  HttpGet#getURI();

EDIT: You didn't mention how you are doing redirect. That works for us because we handle the 302 ourselves.

Sounds like you are using DefaultRedirectHandler. We used to do that. It's kind of tricky to get the current URL. You need to use your own context. Here are the relevant code snippets,

        HttpGet httpget = new HttpGet(url);
HttpContext context = new BasicHttpContext();
HttpResponse response = httpClient.execute(httpget, context);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
throw new IOException(response.getStatusLine().toString());
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(
ExecutionContext.HTTP_REQUEST);
HttpHost currentHost = (HttpHost) context.getAttribute(
ExecutionContext.HTTP_TARGET_HOST);
String currentUrl = (currentReq.getURI().isAbsolute()) ? currentReq.getURI().toString() : (currentHost.toURI() + currentReq.getURI());

The default redirect didn't work for us so we changed but I forgot what was the problem.

HttpClient 302 redirect

If you look at the headers in the response, you'll see this:

First one (https://pcr.apple.com/id868222886):

Content-Length: 0
Location: http://beardycast.libsyn.com/rss

Second one (https://jigsaw.w3.org/HTTP/300/302.html):

Content-Length: 389
Content-Type: text/html;charset=ISO-8859-1
Location: https://jigsaw.w3.org/HTTP/300/Overview.html

So the first server silently redirects you, and the second one provides some additional headers for you:

Strict-Transport-Security: max-age=15552015; includeSubDomains; preload
Public-Key-Pins: pin-sha256="cN0QSpPIkuwpT6iP2YjEo1bEwGpH/yiUn6yhdy+HNto="; pin-sha256="WGJkyYjx1QMdMe0UqlyOKXtydPDVrk7sl2fV+nNm1r4="; pin-sha256="LrKdTxZLRTvyHM4/atX2nquX9BeHRZMCxg3cf4rhc2I="; max-age=864000
X-Frame-Options: deny
X-XSS-Protection: 1; mode=block

And the response body:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Moved</title>
</head>
<body>
<P>This resources has moved, click on the link if your browser doesn't support automatic redirection<BR>
<A HREF="http://jigsaw.w3.org/HTTP/300/Overview.html">http://jigsaw.w3.org/HTTP/300/Overview.html</A></body>
</html>

This is why HttpClient returns non-empty result string - it's not really empty. Your unit tests have wrong design approach, as they do not check the status, but do check only response length, which could be non-empty even for 3** http status codes.

Why can't I download a file when the server returns HTTP 302 Found using HttpClient in C#?

An HTTP response with status code 302 indicates that the requested information is located at the URI specified in the Location header of the response (a redirect essentially).

Considering you have set HttpClientHandler.AllowAutoRedirect, the handler will automatically follow HTTP redirections headers until you reach a response that doesn't have a status code indicating a redirection.

I also don't suspect that the server is redirecting you more than 50 times, which is the default value for HttpClientHandler.MaxAutomaticRedirections so that only leaves one thing.

Either the server is actually returning a failing status code for whatever reason once the response is complete or if it isn't, an important note to be aware of is that unless you are using the .NET Framework (and not .NET Core etc.), HttpClient will not follow redirections from a secure HTTPS endpoint to an insecure HTTP endpoint.

You cannot override automatic redirection dis-allowing HTTPS -> HTTP for security reasons however if you must, parse the Location header yourself until the redirection is complete.

This should work:

var uri = "https://myhost/export/myfile.php";

var initialRequestMessage = new HttpRequestMessage(HttpMethod.Get, URI);

initialRequestMessage.Headers.Add("Cookie", "PHPSESSID=...");

using (var client = new HttpClient())
{
var response = await client.SendAsync(initialRequestMessage);

while (response.StatusCode == HttpStatusCode.Found)
{
Uri redirectedUri = response.Headers.Location;
var requestMessage = new HttpRequestMessage(HttpMethod.Get, redirectedUri);
response = await client.SendAsync(requestMessage);
}

// response is successful or unsuccessful but will not be a redirect
Console.WriteLine(response.StatusCode);
}


Related Topics



Leave a reply



Submit