HTTPClient unable to establish route between https

2019-04-10 15:49发布

问题:

I am testing HttpClient 4.2 by hitting a mixture of http and https links.

HttpClient seems to stick with the protocol from the first call. If the first call is http, then all following https calls fail but http calls are fine. And vice versa.

Here is the test code I used.

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

The second request (https) will fail, but the baidu request is fine.

Caused by: org.apache.http.HttpException: Unable to establish route: planned = {s}->https://www.hotmail.com; current = {s}->http://www.hotmail.com at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:842)

I also have to disable redirection because hotmail redirects request: http://www.hotmail.com -> https://www.hotmail.com or https://www.hotmail.com -> https://www.live.com. A similar error is thrown in either cases.

The wrapper is shown below. It is used to accept all certificates.

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

回答1:

HttpClient should be able to manage connections absolutely transparently to the user. This problem is likely to be caused by a regression introduced in the 4.2 release (see HTTPCLIENT-1193).

Use either PoolingConnectionManager or SingleConnectionManager instead of the default one until 4.2.1 version is released.



回答2:

You are trying to use one connection to communicate to a number of different sites. AFAIR You have to create new connection (== new client) for every unique site.