2012-05-24 2 views
4

Я тестирую HttpClient 4.2, нажимая смесь ссылок http и https.HTTPClient не может установить маршрут между https и http

HttpClient, похоже, придерживается протокола с первого вызова. Если первым вызовом является http, то все последующие вызовы https терпят неудачу, но HTTP-вызовы прекрасны. И наоборот.

Вот тестовый код, который я использовал.

@Test 
public void testNoRedirectMixed() throws ClientProtocolException, IOException { 
    HttpClient httpclient = new DefaultHttpClient(); 
    httpclient=WebClientDevWrapper.wrapClient(httpclient); 
    HttpClientParams.setRedirecting(httpclient.getParams(), false); 

    { 
    HttpGet httpget = new HttpGet("http://www.hotmail.com"); 
    HttpResponse response = httpclient.execute(httpget); 
    HttpEntity entity = response.getEntity(); 
    assertTrue(EntityUtils.toString(entity).indexOf("com")>0); 
    } 

    try { 
    HttpGet httpget = new HttpGet("https://www.hotmail.com"); 
    HttpResponse response = httpclient.execute(httpget); 
    HttpEntity entity = response.getEntity(); 

    }catch (Exception e) { 
     e.printStackTrace(); 
    } 

    { 
    HttpGet httpget = new HttpGet("http://www.baidu.com"); 
    HttpResponse response = httpclient.execute(httpget); 
    HttpEntity entity = response.getEntity(); 
    assertTrue(EntityUtils.toString(entity).indexOf("com")>0); 
    } 
} 

Второй запрос (https) не удастся, но запрос baidu в порядке.

Вызвано: org.apache.http.HttpException: Не удалось установить маршрут: запланировано = {s} ->https://www.hotmail.com; ток = {s} ->http://www.hotmail.com в org.apache.http.impl.client.DefaultRequestDirector.establishRoute (DefaultRequestDirector.java:842)

Я также должен отключить перенаправление, поскольку перенаправляет запрос Hotmail: http://www.hotmail.com ->https://www.hotmail.com или https://www.hotmail.com ->https://www.live.com. Аналогичная ошибка возникает в обоих случаях.

Обертка показана ниже. Он используется для приема всех сертификатов.

public class WebClientDevWrapper { 

    public static HttpClient wrapClient(HttpClient base) { 
     try { 
      SSLContext ctx = SSLContext.getInstance("TLS"); 
      X509TrustManager tm = new X509TrustManager() { 

       public void checkClientTrusted(X509Certificate[] xcs, 
         String string) throws CertificateException { 
       } 

       public void checkServerTrusted(X509Certificate[] xcs, 
         String string) throws CertificateException { 
       } 

       public X509Certificate[] getAcceptedIssuers() { 
        return new X509Certificate[]{}; 
       } 
      }; 
      ctx.init(null, new TrustManager[] { tm }, null); 
      SSLSocketFactory ssf = new SSLSocketFactory(ctx); 
       ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
      ClientConnectionManager ccm = base.getConnectionManager(); 
      SchemeRegistry sr = ccm.getSchemeRegistry(); 
      sr.register(new Scheme("https", ssf, 443)); 
      DefaultHttpClient client= new DefaultHttpClient(ccm, base.getParams()); 
      return client; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 
} 

ответ

3

HttpClient должен иметь возможность управлять соединениями абсолютно прозрачно для пользователя. Эта проблема, вероятно, будет вызвана регрессией, введенной в выпуске 4.2 (see HTTPCLIENT-1193).

Используйте PoolingConnectionManager или SingleConnectionManager вместо стандартного, пока не будет выпущена версия 4.2.1.

+0

спасибо @oleg. Проблема очень хорошо сочетается с билетом (перенаправление от http до https или наоборот в том же домене). Я попытался использовать PoolingClientConnectionManager, но он по-прежнему бросал те же ошибки. Я попробую 4.2.1, когда он будет выпущен. –

0

Вы пытаетесь использовать одно соединение для связи с несколькими различными сайтами. AFAIR Вам нужно создать новое соединение (новый клиент) для каждого уникального сайта.

+0

спасибо, Герман. вы правы, это фактически не имеет ничего общего с http или https. Я думаю, что третий вызов успешный, потому что отказ второго вызова сбрасывает httpclient каким-то образом. Первоначально я столкнулся с типом ошибки, когда страница перенаправляет запрос https на http в том же домене. Есть ли элегантный способ его обнаружить, а затем подключиться к HTTP-запросу с новым соединением (новым httpclient)? –

Смежные вопросы