You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2020/04/12 14:38:26 UTC

[httpcomponents-core] 03/04: Improved TLS configuration of async server endpoints

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch 5.1.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 3ad3d510178e44d04f514dc77925622693c17dcc
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sun Apr 12 11:03:26 2020 +0200

    Improved TLS configuration of async server endpoints
---
 .../nio/ClientHttpProtocolNegotiatorFactory.java   |  18 +++-
 .../nio/ServerHttpProtocolNegotiatorFactory.java   |  27 +++++-
 .../core5/http2/examples/H2FileServerExample.java  |   3 +-
 .../http2/examples/H2FullDuplexServerExample.java  |   3 +-
 .../hc/core5/http2/examples/H2GreetingServer.java  |   3 +-
 .../examples/ReactiveFullDuplexServerExample.java  |   3 +-
 .../hc/core5/benchmark/BenchmarkToolTest.java      |   2 +-
 .../apache/hc/core5/testing/nio/H2AlpnTest.java    |   2 +-
 .../testing/nio/H2ProtocolNegotiationTest.java     |  13 +--
 .../nio/H2ServerAndMultiplexingRequesterTest.java  |   8 +-
 .../testing/nio/H2ServerAndRequesterTest.java      |   6 +-
 .../hc/core5/testing/nio/H2TLSIntegrationTest.java |  21 +++--
 .../core5/testing/nio/Http1AuthenticationTest.java |  11 ++-
 .../testing/nio/Http1ServerAndRequesterTest.java   |  10 +-
 .../core5/testing/reactive/ReactiveClientTest.java |   3 +-
 .../http/impl/bootstrap/HttpAsyncRequester.java    | 103 +++++++++++----------
 .../core5/http/impl/bootstrap/HttpAsyncServer.java |  44 +++++++++
 .../http/impl/nio/ClientHttp1IOEventHandler.java   |   2 +
 .../impl/nio/ClientHttp1IOEventHandlerFactory.java |  13 ++-
 ...IOEventHandler.java => EndpointParameters.java} |  34 ++++---
 .../http/impl/nio/ServerHttp1IOEventHandler.java   |   5 +-
 .../impl/nio/ServerHttp1IOEventHandlerFactory.java |  26 ++++--
 .../http/examples/AsyncFileServerExample.java      |   3 +-
 .../examples/AsyncFullDuplexServerExample.java     |   3 +-
 .../http/examples/AsyncReverseProxyExample.java    |   3 +-
 .../http/examples/AsyncServerFilterExample.java    |   3 +-
 26 files changed, 238 insertions(+), 134 deletions(-)

diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
index 18381df..0f63ae9 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
@@ -33,8 +33,10 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
+import org.apache.hc.core5.http.impl.nio.EndpointParameters;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.net.NamedEndpoint;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.ProtocolIOSession;
 import org.apache.hc.core5.util.Args;
@@ -70,23 +72,29 @@ public class ClientHttpProtocolNegotiatorFactory implements IOEventHandlerFactor
 
     @Override
     public ClientHttpProtocolNegotiator createHandler(final ProtocolIOSession ioSession, final Object attachment) {
-        if (tlsStrategy != null && ioSession.getInitialEndpoint() instanceof HttpHost) {
-            final HttpHost host = (HttpHost) ioSession.getInitialEndpoint();
-            if (URIScheme.HTTPS.same(host.getSchemeName())) {
+        HttpVersionPolicy endpointPolicy = versionPolicy;
+        if (attachment instanceof EndpointParameters) {
+            final NamedEndpoint endpoint = ioSession.getInitialEndpoint();
+            final EndpointParameters params = (EndpointParameters) attachment;
+            if (tlsStrategy != null && endpoint != null && URIScheme.HTTPS.same(params.scheme)) {
+                final HttpHost host = new HttpHost(params.scheme, endpoint.getHostName(), endpoint.getPort());
                 tlsStrategy.upgrade(
                         ioSession,
                         host,
                         ioSession.getLocalAddress(),
                         ioSession.getRemoteAddress(),
-                        attachment,
+                        params.attachment,
                         handshakeTimeout);
             }
+            if (params.attachment instanceof HttpVersionPolicy) {
+                endpointPolicy = (HttpVersionPolicy) params.attachment;
+            }
         }
         return new ClientHttpProtocolNegotiator(
                 ioSession,
                 http1StreamHandlerFactory,
                 http2StreamHandlerFactory,
-                attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : versionPolicy);
+                endpointPolicy);
     }
 
 }
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
index 074aad9..817a895 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
@@ -30,6 +30,8 @@ package org.apache.hc.core5.http2.impl.nio;
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.URIScheme;
+import org.apache.hc.core5.http.impl.nio.EndpointParameters;
 import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
 import org.apache.hc.core5.http2.HttpVersionPolicy;
@@ -68,16 +70,35 @@ public class ServerHttpProtocolNegotiatorFactory implements IOEventHandlerFactor
 
     @Override
     public ServerHttpProtocolNegotiator createHandler(final ProtocolIOSession ioSession, final Object attachment) {
-        if (tlsStrategy != null) {
+        HttpVersionPolicy endpointPolicy = versionPolicy;
+        if (attachment instanceof EndpointParameters) {
+            final EndpointParameters params = (EndpointParameters) attachment;
+            if (tlsStrategy != null && URIScheme.HTTPS.same(params.scheme)) {
+                tlsStrategy.upgrade(
+                        ioSession,
+                        null,
+                        ioSession.getLocalAddress(),
+                        ioSession.getRemoteAddress(),
+                        params.attachment,
+                        handshakeTimeout);
+            }
+            if (params.attachment instanceof HttpVersionPolicy) {
+                endpointPolicy = (HttpVersionPolicy) params.attachment;
+            }
+        } else {
             tlsStrategy.upgrade(
                     ioSession,
                     null,
                     ioSession.getLocalAddress(),
                     ioSession.getRemoteAddress(),
-                    attachment != null ? attachment : versionPolicy,
+                    attachment,
                     handshakeTimeout);
         }
-        return new ServerHttpProtocolNegotiator(ioSession, http1StreamDuplexerFactory, http2StreamMultiplexerFactory, versionPolicy);
+        return new ServerHttpProtocolNegotiator(
+                ioSession,
+                http1StreamDuplexerFactory,
+                http2StreamMultiplexerFactory,
+                endpointPolicy);
     }
 
 }
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FileServerExample.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FileServerExample.java
index eaca5be..daa975f 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FileServerExample.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FileServerExample.java
@@ -46,6 +46,7 @@ import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.nio.AsyncRequestConsumer;
 import org.apache.hc.core5.http.nio.AsyncServerRequestHandler;
@@ -202,7 +203,7 @@ public class H2FileServerExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.print("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.ofDays(Long.MAX_VALUE));
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FullDuplexServerExample.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FullDuplexServerExample.java
index dc922a0..78e5f59 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FullDuplexServerExample.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2FullDuplexServerExample.java
@@ -42,6 +42,7 @@ import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
@@ -235,7 +236,7 @@ public class H2FullDuplexServerExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.print("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.ofDays(Long.MAX_VALUE));
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2GreetingServer.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2GreetingServer.java
index 3105671..aa2513c 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2GreetingServer.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/examples/H2GreetingServer.java
@@ -44,6 +44,7 @@ import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.message.BasicHttpResponse;
 import org.apache.hc.core5.http.nio.AsyncEntityConsumer;
@@ -115,7 +116,7 @@ public class H2GreetingServer {
         }));
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.println("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.ofDays(Long.MAX_VALUE));
diff --git a/httpcore5-reactive/src/test/java/org/apache/hc/core5/reactive/examples/ReactiveFullDuplexServerExample.java b/httpcore5-reactive/src/test/java/org/apache/hc/core5/reactive/examples/ReactiveFullDuplexServerExample.java
index 1e91980..5a91b6f 100644
--- a/httpcore5-reactive/src/test/java/org/apache/hc/core5/reactive/examples/ReactiveFullDuplexServerExample.java
+++ b/httpcore5-reactive/src/test/java/org/apache/hc/core5/reactive/examples/ReactiveFullDuplexServerExample.java
@@ -42,6 +42,7 @@ import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpHeaders;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.BasicEntityDetails;
 import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
@@ -141,7 +142,7 @@ public class ReactiveFullDuplexServerExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.print("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.ofDays(Long.MAX_VALUE));
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/benchmark/BenchmarkToolTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/benchmark/BenchmarkToolTest.java
index 00f93fe..d3195d2 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/benchmark/BenchmarkToolTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/benchmark/BenchmarkToolTest.java
@@ -107,7 +107,7 @@ public class BenchmarkToolTest {
                 .setVersionPolicy(versionPolicy)
                 .create();
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTP);
         final ListenerEndpoint listener = future.get();
         address = (InetSocketAddress) listener.getAddress();
     }
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2AlpnTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2AlpnTest.java
index f4b1b46..6f139da 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2AlpnTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2AlpnTest.java
@@ -181,7 +181,7 @@ public class H2AlpnTest {
     @Test
     public void testALPN() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ProtocolNegotiationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ProtocolNegotiationTest.java
index d38e477..ccc5cfd 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ProtocolNegotiationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ProtocolNegotiationTest.java
@@ -39,6 +39,7 @@ import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.Method;
 import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
@@ -169,12 +170,12 @@ public class H2ProtocolNegotiationTest {
     @Test
     public void testForceHttp1() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_1, null);
         final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
 
@@ -192,12 +193,12 @@ public class H2ProtocolNegotiationTest {
     @Test
     public void testForceHttp2() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_2, null);
         final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
 
@@ -215,12 +216,12 @@ public class H2ProtocolNegotiationTest {
     @Test
     public void testNegotiateProtocol() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.NEGOTIATE, null);
         final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
 
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndMultiplexingRequesterTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndMultiplexingRequesterTest.java
index e8ac72d..a572fce 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndMultiplexingRequesterTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndMultiplexingRequesterTest.java
@@ -187,7 +187,7 @@ public class H2ServerAndMultiplexingRequesterTest {
     @Test
     public void testSequentialRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -230,7 +230,7 @@ public class H2ServerAndMultiplexingRequesterTest {
     @Test
     public void testMultiplexedRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -265,7 +265,7 @@ public class H2ServerAndMultiplexingRequesterTest {
     @Test
     public void testValidityCheck() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -313,7 +313,7 @@ public class H2ServerAndMultiplexingRequesterTest {
     @Test
     public void testMultiplexedRequestCancellation() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndRequesterTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndRequesterTest.java
index 832c185..88cc3ce 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndRequesterTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2ServerAndRequesterTest.java
@@ -190,7 +190,7 @@ public class H2ServerAndRequesterTest {
     @Test
     public void testSequentialRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -233,7 +233,7 @@ public class H2ServerAndRequesterTest {
     @Test
     public void testSequentialRequestsSameEndpoint() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -284,7 +284,7 @@ public class H2ServerAndRequesterTest {
     @Test
     public void testPipelinedRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
index 5a0f53f..9bcfb9d 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
@@ -46,6 +46,7 @@ import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.Method;
 import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
@@ -164,12 +165,12 @@ public class H2TLSIntegrationTest {
                 .create();
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
                 new BasicRequestProducer(Method.POST, target, "/stuff",
                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
@@ -225,12 +226,12 @@ public class H2TLSIntegrationTest {
                 .create();
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
                 new BasicRequestProducer(Method.POST, target, "/stuff",
                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
@@ -291,12 +292,12 @@ public class H2TLSIntegrationTest {
                 .create();
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
                 new BasicRequestProducer(Method.POST, target, "/stuff",
                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
@@ -357,12 +358,12 @@ public class H2TLSIntegrationTest {
                 .create();
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
 
-        final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+        final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
         final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
                 new BasicRequestProducer(Method.POST, target, "/stuff",
                         new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
@@ -442,11 +443,11 @@ public class H2TLSIntegrationTest {
                     .create();
             try {
                 server.start();
-                final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+                final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTPS);
                 final ListenerEndpoint listener = future.get();
                 final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
 
-                final HttpHost target = new HttpHost("https", "localhost", address.getPort());
+                final HttpHost target = new HttpHost(URIScheme.HTTPS.id, "localhost", address.getPort());
                 final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
                         new BasicRequestProducer(Method.POST, target, "/stuff",
                                 new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1AuthenticationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1AuthenticationTest.java
index 554cf4d..8d12aa1 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1AuthenticationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1AuthenticationTest.java
@@ -45,6 +45,7 @@ import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.HttpVersion;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.Method;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncRequesterBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
@@ -53,11 +54,11 @@ import org.apache.hc.core5.http.impl.bootstrap.StandardFilter;
 import org.apache.hc.core5.http.message.BasicHttpRequest;
 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
-import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
 import org.apache.hc.core5.http.nio.entity.AsyncEntityProducers;
 import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
 import org.apache.hc.core5.http.nio.support.AbstractAsyncServerAuthFilter;
+import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
+import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.io.CloseMode;
 import org.apache.hc.core5.net.URIAuthority;
@@ -204,7 +205,7 @@ public class Http1AuthenticationTest {
     @Test
     public void testGetRequestAuthentication() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTP);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -238,7 +239,7 @@ public class Http1AuthenticationTest {
     @Test
     public void testPostRequestAuthentication() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTP);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -276,7 +277,7 @@ public class Http1AuthenticationTest {
     @Test
     public void testPostRequestAuthenticationNoExpectContinue() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), URIScheme.HTTP);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1ServerAndRequesterTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1ServerAndRequesterTest.java
index 484fa9d..1741d91 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1ServerAndRequesterTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1ServerAndRequesterTest.java
@@ -218,7 +218,7 @@ public class Http1ServerAndRequesterTest {
     @Test
     public void testSequentialRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -261,7 +261,7 @@ public class Http1ServerAndRequesterTest {
     @Test
     public void testSequentialRequestsNonPersistentConnection() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -304,7 +304,7 @@ public class Http1ServerAndRequesterTest {
     @Test
     public void testSequentialRequestsSameEndpoint() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -355,7 +355,7 @@ public class Http1ServerAndRequesterTest {
     @Test
     public void testPipelinedRequests() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
@@ -398,7 +398,7 @@ public class Http1ServerAndRequesterTest {
     @Test
     public void testNonPersistentHeads() throws Exception {
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0), scheme);
         final ListenerEndpoint listener = future.get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/reactive/ReactiveClientTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/reactive/ReactiveClientTest.java
index d6511e1..20603d8 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/reactive/ReactiveClientTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/reactive/ReactiveClientTest.java
@@ -50,6 +50,7 @@ import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStreamResetException;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.Method;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
@@ -364,7 +365,7 @@ public class ReactiveClientTest {
 
     private InetSocketAddress startClientAndServer() throws InterruptedException, ExecutionException {
         server.start();
-        final ListenerEndpoint listener = server.listen(new InetSocketAddress(0)).get();
+        final ListenerEndpoint listener = server.listen(new InetSocketAddress(0), URIScheme.HTTP).get();
         final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
         requester.start();
         return address;
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
index 952899b..d7d6387 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncRequester.java
@@ -49,6 +49,7 @@ import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.impl.DefaultAddressResolver;
+import org.apache.hc.core5.http.impl.nio.EndpointParameters;
 import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
 import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
@@ -99,7 +100,7 @@ public class HttpAsyncRequester extends AsyncRequester implements ConnPoolContro
             final IOSessionListener sessionListener,
             final ManagedConnPool<HttpHost, IOSession> connPool) {
         super(eventHandlerFactory, ioReactorConfig, ioSessionDecorator, exceptionCallback, sessionListener,
-                        ShutdownCommand.GRACEFUL_IMMEDIATE_CALLBACK, DefaultAddressResolver.INSTANCE);
+                ShutdownCommand.GRACEFUL_IMMEDIATE_CALLBACK, DefaultAddressResolver.INSTANCE);
         this.connPool = Args.notNull(connPool, "Connection pool");
     }
 
@@ -177,59 +178,63 @@ public class HttpAsyncRequester extends AsyncRequester implements ConnPoolContro
         final Future<PoolEntry<HttpHost, IOSession>> leaseFuture = connPool.lease(
                 host, null, timeout, new FutureCallback<PoolEntry<HttpHost, IOSession>>() {
 
-            @Override
-            public void completed(final PoolEntry<HttpHost, IOSession> poolEntry) {
-                final AsyncClientEndpoint endpoint = new InternalAsyncClientEndpoint(poolEntry);
-                final IOSession ioSession = poolEntry.getConnection();
-                if (ioSession != null && !ioSession.isOpen()) {
-                    poolEntry.discardConnection(CloseMode.IMMEDIATE);
-                }
-                if (poolEntry.hasConnection()) {
-                    resultFuture.completed(endpoint);
-                } else {
-                    final Future<IOSession> futute = requestSession(host, timeout, attachment, new FutureCallback<IOSession>() {
-
-                        @Override
-                        public void completed(final IOSession session) {
-                            session.setSocketTimeout(timeout);
-                            poolEntry.assignConnection(session);
-                            resultFuture.completed(endpoint);
-                        }
-
-                        @Override
-                        public void failed(final Exception cause) {
-                            try {
-                                resultFuture.failed(cause);
-                            } finally {
-                                endpoint.releaseAndDiscard();
-                            }
+                    @Override
+                    public void completed(final PoolEntry<HttpHost, IOSession> poolEntry) {
+                        final AsyncClientEndpoint endpoint = new InternalAsyncClientEndpoint(poolEntry);
+                        final IOSession ioSession = poolEntry.getConnection();
+                        if (ioSession != null && !ioSession.isOpen()) {
+                            poolEntry.discardConnection(CloseMode.IMMEDIATE);
                         }
-
-                        @Override
-                        public void cancelled() {
-                            try {
-                                resultFuture.cancel();
-                            } finally {
-                                endpoint.releaseAndDiscard();
-                            }
+                        if (poolEntry.hasConnection()) {
+                            resultFuture.completed(endpoint);
+                        } else {
+                            final Future<IOSession> future = requestSession(
+                                    host,
+                                    timeout,
+                                    new EndpointParameters(host.getSchemeName(), attachment),
+                                    new FutureCallback<IOSession>() {
+
+                                        @Override
+                                        public void completed(final IOSession session) {
+                                            session.setSocketTimeout(timeout);
+                                            poolEntry.assignConnection(session);
+                                            resultFuture.completed(endpoint);
+                                        }
+
+                                        @Override
+                                        public void failed(final Exception cause) {
+                                            try {
+                                                resultFuture.failed(cause);
+                                            } finally {
+                                                endpoint.releaseAndDiscard();
+                                            }
+                                        }
+
+                                        @Override
+                                        public void cancelled() {
+                                            try {
+                                                resultFuture.cancel();
+                                            } finally {
+                                                endpoint.releaseAndDiscard();
+                                            }
+                                        }
+
+                                    });
+                            resultFuture.setDependency(future);
                         }
+                    }
 
-                    });
-                    resultFuture.setDependency(futute);
-                }
-            }
-
-            @Override
-            public void failed(final Exception ex) {
-                resultFuture.failed(ex);
-            }
+                    @Override
+                    public void failed(final Exception ex) {
+                        resultFuture.failed(ex);
+                    }
 
-            @Override
-            public void cancelled() {
-                resultFuture.cancel();
-            }
+                    @Override
+                    public void cancelled() {
+                        resultFuture.cancel();
+                    }
 
-        });
+                });
         resultFuture.setDependency(leaseFuture);
         return resultFuture;
     }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncServer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncServer.java
index 72e5bd6..1e39f18 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncServer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpAsyncServer.java
@@ -26,14 +26,21 @@
  */
 package org.apache.hc.core5.http.impl.bootstrap;
 
+import java.net.SocketAddress;
+import java.util.concurrent.Future;
+
 import org.apache.hc.core5.annotation.Internal;
+import org.apache.hc.core5.concurrent.FutureCallback;
 import org.apache.hc.core5.function.Callback;
 import org.apache.hc.core5.function.Decorator;
+import org.apache.hc.core5.http.URIScheme;
+import org.apache.hc.core5.http.impl.nio.EndpointParameters;
 import org.apache.hc.core5.http.nio.command.ShutdownCommand;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.IOReactorConfig;
 import org.apache.hc.core5.reactor.IOSession;
 import org.apache.hc.core5.reactor.IOSessionListener;
+import org.apache.hc.core5.reactor.ListenerEndpoint;
 
 /**
  * HTTP/1.1 server side message exchange handler.
@@ -56,4 +63,41 @@ public class HttpAsyncServer extends AsyncServer {
                         ShutdownCommand.GRACEFUL_NORMAL_CALLBACK);
     }
 
+    public Future<ListenerEndpoint> listen(
+            final SocketAddress address,
+            final URIScheme scheme,
+            final Object attachment,
+            final FutureCallback<ListenerEndpoint> callback) {
+        return super.listen(address, new EndpointParameters(scheme.id, attachment), callback);
+    }
+
+    public Future<ListenerEndpoint> listen(
+            final SocketAddress address,
+            final URIScheme scheme,
+            final FutureCallback<ListenerEndpoint> callback) {
+        return listen(address, scheme, null, callback);
+    }
+
+    public Future<ListenerEndpoint> listen(final SocketAddress address, final URIScheme scheme) {
+        return listen(address, scheme, null, null);
+    }
+
+    /**
+     * @deprecated Use {@link #listen(SocketAddress, URIScheme, FutureCallback)}
+     */
+    @Deprecated
+    @Override
+    public Future<ListenerEndpoint> listen(final SocketAddress address, final FutureCallback<ListenerEndpoint> callback) {
+        return super.listen(address, callback);
+    }
+
+    /**
+     * @deprecated Use {@link #listen(SocketAddress, URIScheme)}
+     */
+    @Deprecated
+    @Override
+    public Future<ListenerEndpoint> listen(final SocketAddress address) {
+        return super.listen(address);
+    }
+
 }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java
index 0ed0a6e..cd23cb8 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java
@@ -27,6 +27,7 @@
 
 package org.apache.hc.core5.http.impl.nio;
 
+import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.net.InetAddressUtils;
 
 /**
@@ -36,6 +37,7 @@ import org.apache.hc.core5.net.InetAddressUtils;
  *
  * @since 5.0
  */
+@Internal
 public class ClientHttp1IOEventHandler extends AbstractHttp1IOEventHandler {
 
     public ClientHttp1IOEventHandler(final ClientHttp1StreamDuplexer streamDuplexer) {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
index 9c215a7..2a8b571 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandlerFactory.java
@@ -28,10 +28,12 @@
 package org.apache.hc.core5.http.impl.nio;
 
 import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.net.NamedEndpoint;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
 import org.apache.hc.core5.reactor.ProtocolIOSession;
@@ -44,6 +46,7 @@ import org.apache.hc.core5.util.Timeout;
  * @since 5.0
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
+@Internal
 public class ClientHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
     private final ClientHttp1StreamDuplexerFactory streamDuplexerFactory;
@@ -61,15 +64,17 @@ public class ClientHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
     @Override
     public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
-        if (tlsStrategy != null && ioSession.getInitialEndpoint() instanceof HttpHost) {
-            final HttpHost host = (HttpHost) ioSession.getInitialEndpoint();
-            if (URIScheme.HTTPS.same(host.getSchemeName())) {
+        if (attachment instanceof EndpointParameters) {
+            final EndpointParameters params = (EndpointParameters) attachment;
+            final NamedEndpoint endpoint = ioSession.getInitialEndpoint();
+            if (tlsStrategy != null && endpoint != null && URIScheme.HTTPS.same(params.scheme)) {
+                final HttpHost host = new HttpHost(params.scheme, endpoint.getHostName(), endpoint.getPort());
                 tlsStrategy.upgrade(
                         ioSession,
                         host,
                         ioSession.getLocalAddress(),
                         ioSession.getRemoteAddress(),
-                        attachment,
+                        params.attachment,
                         handshakeTimeout);
             }
         }
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/EndpointParameters.java
similarity index 62%
copy from httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java
copy to httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/EndpointParameters.java
index 0ed0a6e..2a3d54d 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1IOEventHandler.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/EndpointParameters.java
@@ -24,35 +24,33 @@
  * <http://www.apache.org/>.
  *
  */
-
 package org.apache.hc.core5.http.impl.nio;
 
-import org.apache.hc.core5.net.InetAddressUtils;
+import org.apache.hc.core5.annotation.Internal;
+import org.apache.hc.core5.http.URIScheme;
 
 /**
- * {@link org.apache.hc.core5.reactor.IOEventHandler} that implements
- *  client side HTTP/1.1 messaging protocol with full support for
- *  duplexed message transmission and message pipelining.
+ * Endpoint initialization parameters
  *
- * @since 5.0
+ * @since 5.1
  */
-public class ClientHttp1IOEventHandler extends AbstractHttp1IOEventHandler {
+@Internal
+public final class EndpointParameters {
+
+    public final String scheme;
+    public final Object attachment;
 
-    public ClientHttp1IOEventHandler(final ClientHttp1StreamDuplexer streamDuplexer) {
-        super(streamDuplexer);
+    public EndpointParameters(final String scheme, final Object attachment) {
+        this.scheme = scheme != null ? scheme : URIScheme.HTTP.id;
+        this.attachment = attachment;
     }
 
     @Override
     public String toString() {
-        final StringBuilder buf = new StringBuilder();
-        InetAddressUtils.formatAddress(buf, getLocalAddress());
-        buf.append("->");
-        InetAddressUtils.formatAddress(buf, getRemoteAddress());
-        buf.append(" [");
-        streamDuplexer.appendState(buf);
-        buf.append("]");
-        return buf.toString();
+        return "EndpointParameters{" +
+                "scheme=" + scheme +
+                ", attachment=" + attachment +
+                '}';
     }
 
 }
-
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandler.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandler.java
index e2e0d97..e2ffa60 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandler.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandler.java
@@ -27,8 +27,7 @@
 
 package org.apache.hc.core5.http.impl.nio;
 
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.net.InetAddressUtils;
 
 /**
@@ -38,7 +37,7 @@ import org.apache.hc.core5.net.InetAddressUtils;
  *
  * @since 5.0
  */
-@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
+@Internal
 public class ServerHttp1IOEventHandler extends AbstractHttp1IOEventHandler {
 
     public ServerHttp1IOEventHandler(final ServerHttp1StreamDuplexer streamDuplexer) {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
index 0da7931..09ece66 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ServerHttp1IOEventHandlerFactory.java
@@ -28,6 +28,7 @@
 package org.apache.hc.core5.http.impl.nio;
 
 import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.Internal;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
@@ -43,6 +44,7 @@ import org.apache.hc.core5.util.Timeout;
  * @since 5.0
  */
 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
+@Internal
 public class ServerHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
     private final ServerHttp1StreamDuplexerFactory streamDuplexerFactory;
@@ -60,21 +62,29 @@ public class ServerHttp1IOEventHandlerFactory implements IOEventHandlerFactory {
 
     @Override
     public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
-        final boolean tlsSecured;
-        if (tlsStrategy != null) {
-            tlsSecured = tlsStrategy.upgrade(
+        String endpointScheme = URIScheme.HTTP.id;
+        if (attachment instanceof EndpointParameters) {
+            final EndpointParameters params = (EndpointParameters) attachment;
+            endpointScheme = params.scheme;
+            if (tlsStrategy != null && URIScheme.HTTPS.same(endpointScheme)) {
+                tlsStrategy.upgrade(
+                        ioSession,
+                        null,
+                        ioSession.getLocalAddress(),
+                        ioSession.getRemoteAddress(),
+                        params.attachment,
+                        handshakeTimeout);
+            }
+        } else {
+            tlsStrategy.upgrade(
                     ioSession,
                     null,
                     ioSession.getLocalAddress(),
                     ioSession.getRemoteAddress(),
                     attachment,
                     handshakeTimeout);
-        } else {
-            tlsSecured = false;
         }
-        return new ServerHttp1IOEventHandler(streamDuplexerFactory.create(
-                tlsSecured ? URIScheme.HTTPS.id : URIScheme.HTTP.id,
-                ioSession));
+        return new ServerHttp1IOEventHandler(streamDuplexerFactory.create(endpointScheme, ioSession));
     }
 
 }
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFileServerExample.java b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFileServerExample.java
index a8b776c..7b658d1 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFileServerExample.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFileServerExample.java
@@ -43,6 +43,7 @@ import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.Message;
 import org.apache.hc.core5.http.ProtocolException;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.nio.AsyncRequestConsumer;
@@ -168,7 +169,7 @@ public class AsyncFileServerExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         println("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.MAX_VALUE);
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFullDuplexServerExample.java b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFullDuplexServerExample.java
index 8b1b36a..12dd394 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFullDuplexServerExample.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFullDuplexServerExample.java
@@ -42,6 +42,7 @@ import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
@@ -216,7 +217,7 @@ public class AsyncFullDuplexServerExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.print("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.MAX_VALUE);
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
index da0acb1..8136cab 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
@@ -56,6 +56,7 @@ import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.BasicEntityDetails;
 import org.apache.hc.core5.http.impl.Http1StreamListener;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncRequesterBootstrap;
@@ -204,7 +205,7 @@ public class AsyncReverseProxyExample {
 
         requester.start();
         server.start();
-        server.listen(new InetSocketAddress(port));
+        server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         println("Listening on port " + port);
 
         server.awaitShutdown(TimeValue.MAX_VALUE);
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncServerFilterExample.java b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncServerFilterExample.java
index fd8c6b0..216bbd9 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncServerFilterExample.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncServerFilterExample.java
@@ -37,6 +37,7 @@ import org.apache.hc.core5.http.HttpRequest;
 import org.apache.hc.core5.http.HttpResponse;
 import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.Message;
+import org.apache.hc.core5.http.URIScheme;
 import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
 import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
 import org.apache.hc.core5.http.impl.bootstrap.StandardFilter;
@@ -188,7 +189,7 @@ public class AsyncServerFilterExample {
         });
 
         server.start();
-        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port));
+        final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(port), URIScheme.HTTP);
         final ListenerEndpoint listenerEndpoint = future.get();
         System.out.print("Listening on " + listenerEndpoint.getAddress());
         server.awaitShutdown(TimeValue.MAX_VALUE);