【问题标题】:Avoid Circular Redirect using HttpClient 4.1.1使用 HttpClient 4.1.1 避免循环重定向
【发布时间】:2011-07-14 18:33:06
【问题描述】:

如何避免使用 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();
                }

【问题讨论】:

  • 你确定可以避免吗?如果确实存在循环重定向,那么抛出异常似乎是一种合理的指示方式。
  • @nos 感谢您的回复。我收到了相同的循环重定向网址。但是,如果我在浏览器上键入该 url,那么我会从服务器返回三个具有相同 url 的响应。首先是 302 Moved tempo。第二个是找到 302,第三个是 200 ok.. 使用相同的 url...我想抓取这个 url 的内容。

标签: java httpclient


【解决方案1】:

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

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

查看更多信息here

【讨论】:

  • 当前版本已弃用。请改用 RequestConfig.custom().setCircularRedirectsAllowed(true).build()。
  • 其实这不只是为了防止 HttpClient 抛出重定向错误。这意味着重定向仍在发生吗?正如亚当所说,这不需要在服务器上进行永久修复吗?
  • 我仍然收到以下错误:Caused by: org.apache.http.client.RedirectException: Maximum redirects (50) exceeded
  • @anonymous 自然。您的 Web 服务器配置错误,并且它有一个重定向循环(即即使在 50 个请求之后,在这种情况下服务器仍在重定向您)这不是您可以在客户端上修复的。
  • 我不能增加重定向计数吗?找不到任何方法..如果网络服务器配置错误,网络浏览器如何能够正常打开它?这是网址http://www.wsj.com/video/khorasan-meet-the-new-us-terrorist-target/157FA4EF-D44F-49BA-938B-002A91A090A3.html
【解决方案2】:

你只是避开了它。 HttpClient 检测到循环重定向并抛出异常。如果没有“避免”它,它将永远继续重定向(直到您决定终止该进程)。没有很多其他选项,如果这是服务器响应的话。

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

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

有多种方法可以跟踪浏览器的通信。以下是我经常使用的几种方法,按从易到难的顺序排列(恕我直言):

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

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

【讨论】:

  • 感谢您的回复。我收到了相同的循环重定向网址。但是,如果我在浏览器上键入该 url,那么我会从服务器返回三个具有相同 url 的响应。首先是 302 Moved tempo。第二个是找到 302,第三个是 200 ok.. 使用相同的 url...我想抓取这个 url 的内容。
  • 我已经更新了我的答案,提出了一些诊断问题的建议
  • 我在我的 firefox 中使用了 firebug。所以当我看到返回的响应时,在 firebug 中。我看到 302 Found,302 暂时移动,然后 atlast 200 OK 用于我的 firebug 中的相同 url。
  • 我认为您应该尝试查看所有标头,而不仅仅是响应代码,并找出来自 Firefox(正常工作)的请求和来自你的应用程序(不)。您可以使用 telnet 之类的东西来混合和匹配请求中的标头
【解决方案3】:

你可以试试:

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

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

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

【讨论】:

    【解决方案4】:

    从 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);
        }
    }
    

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

    【讨论】:

      【解决方案5】:

      在将您的请求发送到您请求的网址之前,请检查您的请求是否未发送到代理。

      【讨论】:

        【解决方案6】:

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

        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) 不初始化上下文,值将为空。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-05-23
          • 2014-09-18
          • 2011-08-14
          • 1970-01-01
          • 2015-06-17
          • 1970-01-01
          • 2012-02-10
          相关资源
          最近更新 更多