Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
5.0, 5.1
-
None
-
Windows 10.0.19041 Build 19041
Java 11.0.11
Gradle 6.8
Description
When executing a standard GET request with a configured proxy (authenticated or not) using an instance of CloseableHttpAsyncClient, the request fails with "IllegalStateException: No tunnel unless connected."
Is making requests via proxies using an AsyncClient not supported? It is not entirely clear from the current release notes/examples.
Minimal example to reproduce issue, although you will of course need to configure the proxy accordingly given your environment.
import java.util.concurrent.Future; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSession; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; import org.apache.hc.client5.http.async.methods.SimpleRequestProducer; import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; import org.apache.hc.core5.concurrent.FutureCallback; import org.apache.hc.core5.function.Factory; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.StatusLine; import org.apache.hc.core5.http.nio.ssl.TlsStrategy; import org.apache.hc.core5.http2.HttpVersionPolicy; import org.apache.hc.core5.io.CloseMode; import org.apache.hc.core5.reactor.ssl.TlsDetails; public class AsyncMain { public static void main(final String[] args) throws Exception { final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create() .useSystemProperties() .setTlsDetailsFactory(new Factory<SSLEngine, TlsDetails>() { @Override public TlsDetails create(final SSLEngine sslEngine) { return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol()); } }).build(); final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() .setTlsStrategy(tlsStrategy) .build(); try (final CloseableHttpAsyncClient client = HttpAsyncClients.custom() .setVersionPolicy(HttpVersionPolicy.NEGOTIATE) .setConnectionManager(cm) .build()) { client.start(); final HttpClientContext clientContext = HttpClientContext.create(); final HttpHost target = new HttpHost("https", "nghttp2.org"); final HttpHost proxy = new HttpHost("127.0.0.1", 8888); final RequestConfig config = RequestConfig.custom().setProxy(proxy).build(); final SimpleHttpRequest request = SimpleRequestBuilder.get() .setHttpHost(target) .setRequestConfig(config) .setPath("/httpbin/") .build(); System.out.println("Executing request " + request); final Future<SimpleHttpResponse> future = client.execute( SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), clientContext, new FutureCallback<SimpleHttpResponse>() { @Override public void completed(final SimpleHttpResponse response) { System.out.println(request + "->" + new StatusLine(response)); final SSLSession sslSession = clientContext.getSSLSession(); if (sslSession != null) { System.out.println("SSL protocol " + sslSession.getProtocol()); System.out.println("SSL cipher suite " + sslSession.getCipherSuite()); } System.out.println(response.getBody()); } @Override public void failed(final Exception ex) { System.out.println(request + "->" + ex); } @Override public void cancelled() { System.out.println(request + " cancelled"); } }); future.get(); System.out.println("Shutting down"); client.close(CloseMode.GRACEFUL); } } }
The resulting stack trace :
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.IllegalStateException: No tunnel unless connected at org.apache.hc.core5.concurrent.BasicFuture.getResult(BasicFuture.java:72) at org.apache.hc.core5.concurrent.BasicFuture.get(BasicFuture.java:85) at AsyncMain.main(AsyncMain.java:86)Caused by: java.lang.IllegalStateException: No tunnel unless connected at org.apache.hc.core5.util.Asserts.check(Asserts.java:38) at org.apache.hc.client5.http.RouteTracker.tunnelTarget(RouteTracker.java:143) at org.apache.hc.client5.http.impl.async.AsyncConnectExec$4.completed(AsyncConnectExec.java:270) at org.apache.hc.client5.http.impl.async.AsyncConnectExec$5.completed(AsyncConnectExec.java:388) at org.apache.hc.client5.http.impl.async.HttpAsyncMainClientExec$1.consumeResponse(HttpAsyncMainClientExec.java:206) at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamHandler.consumeHeader(ClientHttp1StreamHandler.java:253) at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer.consumeHeader(ClientHttp1StreamDuplexer.java:348) at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer.consumeHeader(ClientHttp1StreamDuplexer.java:80)Caused by: java.lang.IllegalStateException: No tunnel unless connected at org.apache.hc.core5.http.impl.nio.AbstractHttp1StreamDuplexer.onInput(AbstractHttp1StreamDuplexer.java:288) at org.apache.hc.core5.http.impl.nio.AbstractHttp1IOEventHandler.inputReady(AbstractHttp1IOEventHandler.java:64) at org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler.inputReady(ClientHttp1IOEventHandler.java:39) at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:131) at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:51) at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:178) at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:127) at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:85) at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44) at java.base/java.lang.Thread.run(Thread.java:829)