Избегайте циклического перенаправления с использованием 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();
                }

Ответы

Ответ 1

Вы можете установить для ClientPNames.ALLOW_CIRCULAR_REDIRECTS значение true, это позволит перенаправлять в одно и то же место.

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

Подробнее здесь

Ответ 2

Ты просто избегал этого. HttpClient обнаружил циклическое перенаправление и выбрал исключение. Если бы его не "избегали", он продолжал бы перенаправлять навсегда (пока вы не решили убить процесс). Существует не так много других опций, если это отвечает сервер.

Единственный способ по-настоящему избежать циклического цикла перенаправления - исправить сервер.

Если вам интересно, что происходит (например, почему это похоже на работу в браузере, но не из вашей программы), попробуйте включить некоторые дополнительные протоколы HttpClient. В частности, убедитесь, что все HTTP-заголовки отправляются туда и обратно. Затем вы можете посмотреть разговор, когда вы делаете тот же запрос в своем браузере, отмечая различия. Это может быть недостающий файл cookie, безумное обнаружение браузера и т.д.

Существует несколько способов отслеживания ваших сообщений в браузере. Вот несколько способов, которыми я часто пользуюсь, для самых простых и сложных (IMHO):

  • Firefox + HttpFox (или LiveHttpHeaders, Firebug и т.д.)
  • Fiddler (только для Windows)
  • Wireshark/ТСРйитр

Для низкоуровневого тестирования попробуйте использовать telnet (если вы не используете Windows, и в этом случае вам может быть лучше, чем PuTTY/plink) и определение/изменение изменений, вызывающих циклические перенаправления.

Ответ 3

Есть ошибка, которая вызовет циклическую перенаправление в Apache HttpClient с 4.0, она не была исправлена ​​даже в последней версии.

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

Теперь я не буду жаловаться на циркулярное перенаправление.

Ответ 4

Убедитесь, что ваш запрос не отправлен в прокси-сервер, прежде чем отправлять его по указанному вами адресу.

Ответ 5

Вы можете попробовать:

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

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

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