处理 HttpClient 重定向
Posted
技术标签:
【中文标题】处理 HttpClient 重定向【英文标题】:Handling HttpClient Redirects 【发布时间】:2011-03-02 15:12:07 【问题描述】:我正在将一些数据发布到响应 302 Moved Temporarily 的服务器。
我希望 HttpClient 遵循重定向并自动获取新位置,因为我相信这是 HttpClient 的默认行为。但是,我遇到了一个异常并且没有遵循重定向:(
这是相关的代码,任何想法将不胜感激:
HttpParams httpParams = new BasicHttpParams();
HttpClientParams.setRedirecting(httpParams, true);
SchemeRegistry schemeRegistry = registerFactories();
ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(clientConnectionManager, httpParams)
HttpPost postRequest = new HttpPost(url);
postRequest.setHeader(HTTP.CONTENT_TYPE, contentType);
postRequest.setHeader(ACCEPT, contentType);
if (requestBodyString != null)
postRequest.setEntity(new StringEntity(requestBodyString));
return httpClient.execute(postRequest, responseHandler);
【问题讨论】:
你遇到了什么异常? 异常是HttpResponseException 【参考方案1】:对于 HttpClient 4.3:
HttpClient instance = HttpClientBuilder.create()
.setRedirectStrategy(new LaxRedirectStrategy()).build();
对于 HttpClient 4.2:
DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectStrategy(new LaxRedirectStrategy());
对于 HttpClient :
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;
);
【讨论】:
谢谢!想知道他们流畅的 api 是否可以做到这一点? 我希望 HttpClient 在重定向后使用其表单数据重播我的原始 POST 请求,但是,发出了 HTTP GET 请求。我知道这是规范,但对我来说没用:( 如果您使用RequestConfig
,在构建配置时可以使用两种方法:setRedirectsEnabled
和setRelativeRedirectsAllowed
,像这样使用:org.apache.http.client.config.RequestConfig reqCfg = RequestConfig.copy(RequestConfig.DEFAULT).setRedirectsEnabled(true).setRelativeRedirectsAllowed(true).build();
,然后像这样使用它:@987654328 @【参考方案2】:
HttpClient 的默认行为符合 HTTP 规范 (RFC 2616) 的要求
10.3.3 302 找到 ... 如果收到 302 状态代码以响应其他请求 与 GET 或 HEAD 相比,用户代理不能自动重定向 请求,除非它可以被用户确认,因为这可能 更改发出请求的条件。您可以通过继承 DefaultRedirectStrategy 并覆盖其#isRedirected() 方法来覆盖 HttpClient 的默认行为。
【讨论】:
我已经覆盖了 DefaultRedirectHandler 的 #isRedirectRequested() 以考虑 POST 方法并且它按预期工作。谢谢! 如何使用 httpPost 并覆盖 DefaultRedirectHandler 的 #isRedirectRequested() ? 302 行为在RFC 7231 中重新定义:“用户代理可以使用位置字段值进行自动重定向。”【参考方案3】:默认情况下似乎禁用了 http 重定向。我尝试启用,它可以工作,但我的问题仍然存在错误。但是我们仍然可以务实地处理重定向。我认为你的问题可以解决: 这么老的代码:
androidHttpClient httpClient = AndroidHttpClient.newInstance("User-Agent");
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
long contentSize = httpResponse.getEntity().getContentLength();
如果发生 http 重定向,此代码将返回 contentSize = -1
然后我在尝试启用默认跟随重定向后自己处理重定向
AndroidHttpClient client;
HttpGet httpGet;
HttpResponse response;
HttpHeader httpHeader;
private void handleHTTPRedirect(String url) throws IOException
if (client != null)
client.close();
client = AndroidHttpClient.newInstance("User-Agent");
httpGet = new HttpGet(Network.encodeUrl(url));
response = client.execute(httpGet);
httpHeader = response.getHeaders("Location");
while (httpHeader.length > 0)
client.close();
client = AndroidHttpClient.newInstance("User-Agent");
httpGet = new HttpGet(Network.encodeUrl(httpHeader[0].getValue()));
response = client.execute(httpGet);
httpHeader = response.getHeaders("Location");
使用中
handleHTTPRedirect(url);
long contentSize = httpResponse.getEntity().getContentLength();
谢谢 阮
【讨论】:
只是提示,您可能应该限制重定向计数,这种方法可能*导致 ANR,因为恶意或编程不当的内容会不断重定向。【参考方案4】:我的解决方案是使用 HttClient。我不得不将响应发回给调用者。这是我的解决方案
CloseableHttpClient httpClient = HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
//this reads the input stream from POST
ServletInputStream str = request.getInputStream();
HttpPost httpPost = new HttpPost(path);
HttpEntity postParams = new InputStreamEntity(str);
httpPost.setEntity(postParams);
HttpResponse httpResponse = null ;
int responseCode = -1 ;
StringBuffer response = new StringBuffer();
try
httpResponse = httpClient.execute(httpPost);
responseCode = httpResponse.getStatusLine().getStatusCode();
logger.info("POST Response Status:: for file ", responseCode, request.getQueryString());
//return httpResponse ;
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent()));
String inputLine;
while ((inputLine = reader.readLine()) != null)
response.append(inputLine);
reader.close();
logger.info(" Final Complete Response " + response.toString());
httpClient.close();
catch (Exception e)
logger.error("Exception ", e);
finally
IOUtils.closeQuietly(httpClient);
// Return the response back to caller
return new ResponseEntity<String>(response.toString(), HttpStatus.ACCEPTED);
【讨论】:
以上是关于处理 HttpClient 重定向的主要内容,如果未能解决你的问题,请参考以下文章