2011-07-14 32 views
15

如何避免使用HttpClient 4.1.1的循環重定向。由於我得到的錯誤是這樣的: -避免使用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(); 
       } 
+0

你確定你能避免呢?如果確實存在循環重寫,拋出異常似乎是一種合理的方式來表明這一點。 – nos

+0

@nos感謝回答回來..我得到相同的URL回圓形重定向。但是,如果我在瀏覽器上輸入該網址,那麼我會從服務器獲得三次具有相同網址的回覆。首先是302移動節奏。第二是302發現,第三是200好..與相同的網址...我想抓住這個網址的內容。 – ferhan

回答

31

您可以將ClientPNames.ALLOW_CIRCULAR_REDIRECTS設置爲true,這將允許重定向到相同的位置。

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

查看更多信息here

+0

鏈接已損壞。 – Youngjae

+8

這是用過的版本。使用RequestConfig.custom()。setCircularRedirectsAllowed(true).build()來代替。 – keiki

+0

其實這不僅僅是爲了防止HttpClient拋出重定向錯誤。這意味着重定向仍在發生?正如亞當所說,這不需要永久修復服務器? –

2

你只是避免它。 HttpClient檢測到循環重定向並拋出異常。如果沒有被「避免」,它會繼續永久重定向(直到你決定殺死該進程)。沒有太多的其他選項,如果這是服務器響應。

真正避免循環重定向循環的唯一方法是修復服務器。

如果您想知道發生了什麼事情(比如爲什麼它在瀏覽器中查找,而不是從程序中查找),請嘗試打開一些額外的HttpClient日誌記錄。特別是,確保您可以看到來回發送的所有HTTP頭。然後,當您在瀏覽器中發出相同的請求時,您可以查看發生的對話,注意不同之處。它可能是一個缺失的cookie,瘋狂的瀏覽器檢測等...

有很多跟蹤瀏覽器通信的方法。下面是我經常用的,爲了從簡單到困難的幾種方法(恕我直言):

  • 火狐+ HttpFox(或的LiveHTTPHeaders,螢火蟲等)
  • Fiddler(僅限於Windows)
  • 的Wireshark/tcpdump的

對於低級別的測試,嘗試使用telnet(除非你使用的是Windows,在這種情況下,你可能會喜歡的東西PuTTY/plink更好)和執政的進/出什麼樣的變化引起的圓形重定向。

+0

感謝回答回來..我得到相同的URL回圓形重定向。但是,如果我在瀏覽器上輸入該網址,那麼我會從服務器獲得三次具有相同網址的回覆。首先是302移動節奏。第二是302發現,第三是200好..與相同的網址...我想抓住這個網址的內容。 – ferhan

+0

我已經更新了我的答案跟在我的Firefox診斷我使用螢火問題 –

+0

一些建議..所以,當我看到響應後面的螢火蟲。我看到302發現,302暫時搬遷,然後atlast 200 OK了在我的螢火蟲相同的網址。 – ferhan

2

有,會導致循環重定向在Apache的HttpClient的,因爲4.0中的錯誤,它甚至沒有在最新版本中修復。

在DefaultRequestDirector.java,它會創建一個HttpRedirect進行重定向,它會重用所有標題在原始HTTPGET,這裏的問題是,它還會重用主機頭,這意味着服務器仍然會得到原來的它試圖重定向到新的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); 
    } 
} 

現在我不會抱怨的通知重定向。

0

檢查您的請求在發送到您請求的網址之前是否未發送至代理服務器。

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