Search code examples
proxyapache-httpcomponents

Apache Http Components - How to timeout CONNECT request to a proxy?


Timeout Without Using Proxy

I start netcat in my local as follows, which basically listens to connections on port 9090:

netcat -l -p 9090

And using Apache HttpComponents, I create a connection to it with a timeout of 4 seconds..

RequestConfig requestConfig = RequestConfig.custom()
        .setSocketTimeout(4000)
        .setConnectTimeout(4000)
        .setConnectionRequestTimeout(4000)
        .build();

HttpGet httpget = new HttpGet("http://127.0.0.1:9090");
httpget.setConfig(requestConfig);

try (CloseableHttpResponse response = HttpClients.createDefault().execute(httpget)) {}

In terminal (where I have netcat running) I see:

??]?D???;#???9?Mۡ?NR?w?{)?V?$?(=?&?*kj?
?5??98?#?'<?%?)g@?  ?/??32?,?+?0??.?2???/??-?1???D

<!-- 4 seconds later -->
read(net): Connection reset by peer

In client side what I see is:

Exception in thread "main" org.apache.http.conn.ConnectTimeoutException: 
Connect to 127.0.0.1:9090 [/127.0.0.1] failed: Read timed out

This is all expected.

Timeout Using Proxy

I change the client code slightly and configure a proxy, following the docs here.

RequestConfig requestConfig = RequestConfig.custom()
         .setSocketTimeout(4000)
         .setConnectTimeout(4000)
         .setConnectionRequestTimeout(4000)
         .build();

HttpHost proxy = new HttpHost("127.0.0.1", 9090);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CloseableHttpClient httpclient = HttpClients.custom()
        .setRoutePlanner(routePlanner)
        .build();

HttpGet httpget = new HttpGet("https://127.0.0.1:9090");
httpget.setConfig(requestConfig);

try (CloseableHttpResponse response = httpclient.execute(httpget)) {}

And again start netcat, and this time on serverside

CONNECT 127.0.0.1:9090 HTTP/1.1
Host: 127.0.0.1:9090
User-Agent: Apache-HttpClient/4.4.1 (Java/1.8.0_212)

But timeout is not working for CONNECT. I just wait forever..

How can I configure the httpclient to timeout for 4 seconds just like in the first case I described?


Solution

  • RequestConfig only take effect once a connection to the target via the specific route has been fully established . They do not apply to the SSL handshake or any CONNECT requests that take place prior to the main message exchange.

    Configure socket timeout at the ConnectionManager level to ensure connection level operations time out after a certain period of inactivity.