HTTPClient重定向
0
使用的HTTPClient版本4.5.2,默认使用的重定向策略是DefaultRedirectStrategy
。
如果是使用的POST
,然后301
重定向是不会执行重定向后的请求的,而是直接获取到301
状态码。
主要的代码:
public boolean isRedirected(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws ProtocolException {
Args.notNull(request, "HTTP request");
Args.notNull(response, "HTTP response");
final int statusCode = response.getStatusLine().getStatusCode();
final String method = request.getRequestLine().getMethod();
final Header locationHeader = response.getFirstHeader("location");
switch (statusCode) {
case HttpStatus.SC_MOVED_TEMPORARILY:
return isRedirectable(method) && locationHeader != null;
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_TEMPORARY_REDIRECT:
return isRedirectable(method);
case HttpStatus.SC_SEE_OTHER:
return true;
default:
return false;
} //end of switch
}
private static final String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME,
HttpHead.METHOD_NAME
};
protected boolean isRedirectable(final String method) {
for (final String m: REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
}
除了303
状态码,其他的就判断请求方法,请求方法支持的只有GET
和HEAD
两种,所以POST
请求是不会被重定向,除非返回的是303
状态码。
下面是一个我实现的重定向策略:
package com.acgist.utils.http;
import java.net.URI;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.ProtocolException;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.protocol.HttpContext;
/**
* 重定向策略
* 307重定向请求,使用原请求方法,POST携带POST参数
* 303/302/301重定向到GET请求,POST请求将不携带POST参数
*/
public class AcgistRedirectStrategy implements RedirectStrategy {
@Override
public boolean isRedirected(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException {
// final String method = request.getRequestLine().getMethod();
final int statusCode = response.getStatusLine().getStatusCode();
switch (statusCode) {
case HttpStatus.SC_TEMPORARY_REDIRECT:
case HttpStatus.SC_MOVED_PERMANENTLY:
case HttpStatus.SC_MOVED_TEMPORARILY:
case HttpStatus.SC_SEE_OTHER:
return true;
default:
return false;
}
}
@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();
final int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_TEMPORARY_REDIRECT) { // 307使用原始request
return RequestBuilder.copy(request).setUri(uri).build();
} else { // 其他直接转换为GET请求,参数使用返回的location携带,原请求参数将会丢失
return new HttpGet(uri);
}
}
private URI getLocationURI(final HttpRequest request, final HttpResponse response, final HttpContext context) throws ProtocolException {
final Header locationHeader = response.getFirstHeader("location");
if (locationHeader == null) {
throw new ProtocolException("未返回重定向location首部");
}
final String location = locationHeader.getValue();
final URI requestURI = URI.create(request.getRequestLine().getUri());
return requestURI.resolve(location);
}
}