简体   繁体   中英

HTTP2 url loading succesfuly in browser but fails in httpclient5

I am trying to create a httpclient 5 example which loads the URL using asynchttpclient(Asynchronous multiplexing) with this example , I have configured the tomcat 9 to accept http2 protocol using the conf/server.xml configuration as follows

<Connector
       protocol="org.apache.coyote.http11.Http11NioProtocol"
       port="8443" maxThreads="200"
       scheme="https" secure="true" SSLEnabled="true"
       keystoreFile="conf/xxx.keystore" keystorePass="xxx#"
       clientAuth="false" sslProtocol="TLS"><UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/></Connector>

and my program as follows,

    final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustAllStrategy()).build();
    final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(new H2TlsStrategy(sslContext, NoopHostnameVerifier.INSTANCE)).build();
    final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();
    final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, null, ioReactorConfig, connectionManager);


    client.start();

    final HttpHost target = new HttpHost("localhost", 8084, "https");
    System.out.println(target.getPort());
    final Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
    final AsyncClientEndpoint endpoint = leaseFuture.get(45, TimeUnit.SECONDS);
    try {
        final String[] requestUris = new String[] {"/index.html"};

        final CountDownLatch latch = new CountDownLatch(requestUris.length);
        for (final String requestUri: requestUris) {
            final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri);

            endpoint.execute(SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() {
                        @Override
                        public void completed(final SimpleHttpResponse response) {
                            latch.countDown();
                            System.out.println(requestUri + "->" + response.getCode());
                            System.out.println(response.getBody());
                        }

                        @Override
                        public void failed(final Exception ex) {
                            latch.countDown();
                            System.out.println(requestUri + "->" + ex);
                            ex.printStackTrace();
                        }

                        @Override
                        public void cancelled() {
                            latch.countDown();
                            System.out.println(requestUri + " cancelled");
                        }

                    });
        }
        latch.await();
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        endpoint.releaseAndReuse();
    }

    client.shutdown(ShutdownType.GRACEFUL);

The tomcat configuration works as the page loads in borwser with h2 protocol, but it fails with httpclient 5 with the following exception

/index.html->org.apache.hc.core5.http.ConnectionClosedException: Connection closed
org.apache.hc.core5.http.ConnectionClosedException: Connection closed
    at org.apache.hc.core5.http2.impl.nio.FrameInputBuffer.read(FrameInputBuffer.java:146)
    at org.apache.hc.core5.http2.impl.nio.AbstractHttp2StreamMultiplexer.onInput(AbstractHttp2StreamMultiplexer.java:415)
    at org.apache.hc.core5.http2.impl.nio.AbstractHttp2IOEventHandler.inputReady(AbstractHttp2IOEventHandler.java:63)
    at org.apache.hc.core5.http2.impl.nio.ClientHttp2IOEventHandler.inputReady(ClientHttp2IOEventHandler.java:38)
    at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:117)
    at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:50)
    at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:173)
    at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:123)
    at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:80)
    at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
    at java.lang.Thread.run(Thread.java:748)

Any help on this will be greatly appreciated

Thanks In Advance

On enabling the tomcat logs, I can see the following,

org.apache.coyote.AbstractProtocol$ConnectionHandler.process Failed to create Processor for negotiated protocol [h2c]

Even this issue is fixed when I update the client code to java 9, but is that possible to make it work with java 8.

ps: I know java 8 does not support ALPN, but let me know if any means I can make it work with java 8.

I faced a similar problem, and found it was due to the request protocol being used as https. Since I was already setting the TLS Strategy for the client, changing the protocol to simple 'http' solved the problem. Replace the line : final HttpHost target = new HttpHost("localhost", 8084, "https"); by final HttpHost target = new HttpHost("localhost", 8084, "http");

By using conscrypt as a default provider and make using of custom TLSStrategy we can make it work with jdk1.8, refer,

https://stackoverflow.com/a/53399363/2236001

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM