使用HttpClient 4.1.1避免循环重定向

时间:2011-07-14 18:33:06

标签: java httpclient

如何使用HttpClient 4.1.1避免循环重定向。因为我得到这样的错误: -

executing requestGET http://home.somehost.com/Mynet/pages/cHome.xhtml HTTP/1.1
org.apache.http.client.ClientProtocolException
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:822)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at edu.uci.ics.crawler4j.url.WebURL.setURL(WebURL.java:122)
    at edu.uci.ics.crawler4j.crawler.CrawlController.addSeed(CrawlController.java:207)
    at edu.uci.ics.crawler4j.example.advanced.Controller.main(Controller.java:31)
Caused by: org.apache.http.client.CircularRedirectException: Circular redirect to 'http://home.somehost.com/Mynet/pages/Home.xhtml'
    at org.apache.http.impl.client.DefaultRedirectStrategy.getLocationURI(DefaultRedirectStrategy.java:168)
    at org.apache.http.impl.client.DefaultRedirectStrategy.getRedirect(DefaultRedirectStrategy.java:193)
    at org.apache.http.impl.client.DefaultRequestDirector.handleResponse(DefaultRequestDirector.java:1021)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:482)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)

这是我的代码......

DefaultHttpClient client = null;

        try
        {
            // Set url
            //URI uri = new URI(url.toString());

            client = new DefaultHttpClient();

            client.getCredentialsProvider().setCredentials(
                    new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),
                    new UsernamePasswordCredentials("test", "test"));


            URL url1 = new URL (url);
            HttpURLConnection connection = (HttpURLConnection) url1.openConnection();
            connection.setFollowRedirects(false);

            HttpGet request = new HttpGet(url);
            final HttpParams params = new BasicHttpParams();
            HttpClientParams.setRedirecting(params, false);
            HttpContext context = new BasicHttpContext();

            System.out.println("----------------------------------------");
            System.out.println("executing request" + request.getRequestLine());
            HttpResponse response = client.execute(request, context);
            HttpEntity entity = response.getEntity();


            System.out.println(response.getStatusLine());
                    InputStream content = entity.getContent();
                    BufferedReader in   = 
                        new BufferedReader (new InputStreamReader (content));
                    String line;
                    while ((line = in.readLine()) != null) {
                       // System.out.println(line);
                    }
                } catch(Exception e) {
                    e.printStackTrace();
                }

6 个答案:

答案 0 :(得分:32)

您可以将ClientPNames.ALLOW_CIRCULAR_REDIRECTS设置为true,这将允许重定向到同一位置。

  client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true); 

查看更多信息here

答案 1 :(得分:2)

你只是避开了它。 HttpClient检测到循环重定向并引发异常。如果没有“避免”,它将继续永远重定向(直到你决定杀死这个过程)。如果这是服务器响应的内容,则没有很多其他选项。

真正避免循环重定向循环的唯一方法是修复服务器。

如果您想知道发生了什么(比如为什么它似乎可以在浏览器中查找而不是从您的程序中找到),请尝试启用一些额外的HttpClient日志记录。特别是,请确保您可以看到所有来回发送的HTTP标头。然后,您可以查看在浏览器中发出相同请求时发生的对话,并注明差异。它可能是一个丢失的cookie,疯狂的浏览器检测等...

有许多方法可以跟踪浏览器的通信。以下是我经常使用的几种方式,从最简单到最难(IMHO):

  • Firefox + HttpFox(或LiveHttpHeaders,Firebug等......)
  • Fiddler(仅限Windows)
  • 的Wireshark / tcpdump的

对于低级别测试,请尝试使用telnet(除非您使用Windows,在这种情况下,您可能会更好地使用PuTTY/plink之类的内容)并排除/更改导致循环重定向的更改。

答案 2 :(得分:2)

自4.0以来,Apache HttpClient中存在一个导致循环重定向的错误,即使在最新版本中也没有修复。

在DefaultRequestDirector.java中,它创建一个HttpRedirect来执行重定向,它将重用原始HttpGet中的所有头文件,这里的问题是它还将重用 Host 头,这意味着服务器将在尝试重定向到新URI后仍然会获得原始主机。

我通过重新实现DefaultRequestDirector来修复此问题:

public class RedirectRequestDirector extends DefaultRequestDirector
{
    RedirectRequestDirector(
            final HttpRequestExecutor requestExec,
            final ClientConnectionManager conman,
            final ConnectionReuseStrategy reustrat,
            final ConnectionKeepAliveStrategy kastrat,
            final HttpRoutePlanner rouplan,
            final HttpProcessor httpProcessor,
            final HttpRequestRetryHandler retryHandler,
            final RedirectHandler redirectHandler,
            final AuthenticationHandler targetAuthHandler,
            final AuthenticationHandler proxyAuthHandler,
            final UserTokenHandler userTokenHandler,
            final HttpParams params) 
    {
        super(requestExec, conman, reustrat, kastrat, rouplan, httpProcessor, retryHandler, redirectHandler, targetAuthHandler, proxyAuthHandler, userTokenHandler, params);

    }
    @Override
    protected RoutedRequest handleResponse(RoutedRequest roureq,
            HttpResponse response,
            HttpContext context)
                    throws HttpException, IOException
    {
        RoutedRequest req = super.handleResponse(roureq, response, context);
        if(req != null)
        {
            String redirectTarget = req.getRoute().getTargetHost().getHostName();
            req.getRequest().getOriginal().setHeader("Host", redirectTarget);
        }
        return req;
    }

}

和DefaultHttpClient:

public class RedirectHttpClient extends DefaultHttpClient
{
    @Override
    protected RequestDirector createClientRequestDirector(
            final HttpRequestExecutor requestExec,
            final ClientConnectionManager conman,
            final ConnectionReuseStrategy reustrat,
            final ConnectionKeepAliveStrategy kastrat,
            final HttpRoutePlanner rouplan,
            final HttpProcessor httpProcessor,
            final HttpRequestRetryHandler retryHandler,
            final RedirectHandler redirectHandler,
            final AuthenticationHandler targetAuthHandler,
            final AuthenticationHandler proxyAuthHandler,
            final UserTokenHandler stateHandler,
            final HttpParams params) {
        return new RedirectRequestDirector(
                requestExec,
                conman,
                reustrat,
                kastrat,
                rouplan,
                httpProcessor,
                retryHandler,
                redirectHandler,
                targetAuthHandler,
                proxyAuthHandler,
                stateHandler,
                params);
    }
}

现在我不会抱怨循环重定向。

答案 3 :(得分:0)

检查您的请求是否未发送到代理,然后再发送到您请求的网址。

答案 4 :(得分:0)

您可以尝试:

RequestConfig requestConfig = RequestConfig.custom()
                              .setCircularRedirectsAllowed(true)
                              .build();

HttpClient httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(requestConfig)
                        .setRedirectStrategy(new LaxRedirectStrategy())
                        .build();

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);

答案 5 :(得分:0)

我在春季版本升级时遇到了这个问题,在我的情况下,上下文未正确初始化。

org.apache.http.impl.client.DefaultRedirectStrategy中:

RedirectLocations redirectLocations = (RedirectLocations) clientContext.getAttribute(
                HttpClientContext.REDIRECT_LOCATIONS);

clientContext的值应为basicHttpContext,但Spring Web (4.3.x.RELEASE)正在初始化上下文:

org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal();

clientContext的值正在更改,这将导致循环重定向错误。 Spring Web(3.2.x.RELEASE)不会初始化上下文,并且值将为null。