5

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;
        }
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267

2 Answers2

3

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.

ok2c
  • 26,450
  • 5
  • 63
  • 71
  • thanks @oleg. The problem matches the ticket very well (a redirection from http to https or vice versa on the same domain). I tried using PoolingClientConnectionManager, but it still threw the same errors. I will try 4.2.1 when it is released. – Payton Cartman May 28 '12 at 04:04
0

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.

Germann Arlington
  • 3,315
  • 2
  • 17
  • 19
  • thanks, Germann. you are right, this actually has nothing to do with http or https. I think the third call is successful because the second call's failure resets the httpclient somehow. I originally ran into type of error when a page redirects https request to http within the same domain. Is there any elegant way to detect it and then connect to the http request with a new connection (a new httpclient)? – Payton Cartman May 24 '12 at 15:50