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 2017/05/09 19:58:04 UTC
[12/50] [abbrv] httpcomponents-core git commit: HTTP protocol version
negotiation
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2TlsSupport.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2TlsSupport.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2TlsSupport.java
index 836ccaa..d4333ad 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2TlsSupport.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2TlsSupport.java
@@ -27,17 +27,19 @@
package org.apache.hc.core5.http2.ssl;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
+import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.net.NamedEndpoint;
import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
+import org.apache.hc.core5.ssl.ReflectionSupport;
public final class H2TlsSupport {
@@ -359,54 +361,43 @@ public final class H2TlsSupport {
return enabledCiphers != null ? enabledCiphers.toArray(new String[enabledCiphers.size()]) : ciphers;
}
- static void applyParameter(final SSLParameters sslParameters, final String name, final Class type, final Object value) {
- try {
- final Class<? extends SSLParameters> clazz = sslParameters.getClass();
- final Method method = clazz.getMethod("set" + name, type);
- method.invoke(sslParameters, value);
- } catch (final Exception ignore) {
- }
- }
-
- @SuppressWarnings("unchecked")
- static <T> T getParameter(final SSLParameters sslParameters, final String name, final Class<T> resultType) {
- try {
- final Class<? extends SSLParameters> clazz = sslParameters.getClass();
- final Method method = clazz.getMethod("get" + name);
- return resultType.cast(method.invoke(sslParameters));
- } catch (final Exception ignore) {
- return null;
- }
- }
-
public static void setEnableRetransmissions(final SSLParameters sslParameters, final boolean value) {
- applyParameter(sslParameters, "EnableRetransmissions", Boolean.TYPE, value);
+ ReflectionSupport.callSetter(sslParameters, "EnableRetransmissions", Boolean.TYPE, value);
}
public static void setApplicationProtocols(final SSLParameters sslParameters, final String[] values) {
- applyParameter(sslParameters, "ApplicationProtocols", String[].class, values);
+ ReflectionSupport.callSetter(sslParameters, "ApplicationProtocols", String[].class, values);
}
- public static Boolean getEnableRetransmissions(final SSLParameters sslParameters) {
- return getParameter(sslParameters, "EnableRetransmissions", Boolean.class);
- }
-
- public static String[] getApplicationProtocols(final SSLParameters sslParameters) {
- return getParameter(sslParameters, "ApplicationProtocols", String[].class);
- }
-
- public static SSLSessionInitializer enforceRequirements(final SSLSessionInitializer initializer) {
+ public static SSLSessionInitializer enforceRequirements(
+ final Object attachment,
+ final SSLSessionInitializer initializer) {
return new SSLSessionInitializer() {
@Override
- public void initialize(final NamedEndpoint endpoint, final SSLParameters sslParameters) {
+ public void initialize(final NamedEndpoint endpoint, final SSLEngine sslEngine) {
+ final SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setProtocols(excludeBlacklistedProtocols(sslParameters.getProtocols()));
sslParameters.setCipherSuites(excludeBlacklistedCiphers(sslParameters.getCipherSuites()));
setEnableRetransmissions(sslParameters, false);
- setApplicationProtocols(sslParameters, new String[] { "h2" });
-
+ final HttpVersionPolicy versionPolicy = attachment instanceof HttpVersionPolicy ?
+ (HttpVersionPolicy) attachment : HttpVersionPolicy.NEGOTIATE;
+ final String[] appProtocols;
+ switch (versionPolicy) {
+ case FORCE_HTTP_1:
+ appProtocols = new String[] { ApplicationProtocols.HTTP_1_1.id };
+ break;
+ case FORCE_HTTP_2:
+ appProtocols = new String[] { ApplicationProtocols.HTTP_2.id };
+ break;
+ default:
+ appProtocols = new String[] { ApplicationProtocols.HTTP_2.id, ApplicationProtocols.HTTP_1_1.id };
+ break;
+ }
+ setApplicationProtocols(sslParameters, appProtocols);
+ sslEngine.setSSLParameters(sslParameters);
if (initializer != null) {
- initializer.initialize(endpoint, sslParameters);
+ initializer.initialize(endpoint, sslEngine);
}
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/SecurePortStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/SecurePortStrategy.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/SecurePortStrategy.java
new file mode 100644
index 0000000..3a4538d
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/SecurePortStrategy.java
@@ -0,0 +1,41 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.ssl;
+
+import java.net.SocketAddress;
+
+/**
+ * Side-side strategy to determine if local endpoint should be secured with TLS.
+ *
+ * @since 5.0
+ */
+public interface SecurePortStrategy {
+
+ boolean isSecure(SocketAddress localAddress);
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestClient.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestClient.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestClient.java
index f846498..b956aa0 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestClient.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestClient.java
@@ -38,8 +38,10 @@ import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.http2.impl.Http2Processors;
import org.apache.hc.core5.http2.impl.nio.bootstrap.AsyncPushConsumerRegistry;
@@ -80,8 +82,21 @@ public class Http2TestClient extends AsyncRequester {
start(new InternalClientHttp2EventHandlerFactory(
httpProcessor,
pushConsumerRegistry,
- CharCodingConfig.DEFAULT,
+ HttpVersionPolicy.FORCE_HTTP_2,
h2Config,
+ H1Config.DEFAULT,
+ CharCodingConfig.DEFAULT,
+ sslContext));
+ }
+
+ public void start(final HttpProcessor httpProcessor, final H1Config h1Config) throws IOException {
+ start(new InternalClientHttp2EventHandlerFactory(
+ httpProcessor,
+ pushConsumerRegistry,
+ HttpVersionPolicy.FORCE_HTTP_1,
+ H2Config.DEFAULT,
+ h1Config,
+ CharCodingConfig.DEFAULT,
sslContext));
}
@@ -89,6 +104,10 @@ public class Http2TestClient extends AsyncRequester {
start(Http2Processors.client(), h2Config);
}
+ public void start(final H1Config h1Config) throws IOException {
+ start(Http2Processors.client(), h1Config);
+ }
+
public void start() throws Exception {
start(H2Config.DEFAULT);
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestServer.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestServer.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestServer.java
index cbc0f7f..3264cb6 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestServer.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/Http2TestServer.java
@@ -35,7 +35,6 @@ import javax.net.ssl.SSLContext;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.config.CharCodingConfig;
import org.apache.hc.core5.http.config.H1Config;
-import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
import org.apache.hc.core5.http.impl.HttpProcessors;
import org.apache.hc.core5.http.impl.bootstrap.AsyncServerExchangeHandlerRegistry;
import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
@@ -43,6 +42,7 @@ import org.apache.hc.core5.http.nio.support.BasicServerExchangeHandler;
import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
import org.apache.hc.core5.http.nio.support.ResponseHandler;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.http2.impl.Http2Processors;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
@@ -90,8 +90,10 @@ public class Http2TestServer extends AsyncServer {
start(new InternalServerHttp2EventHandlerFactory(
httpProcessor,
handlerRegistry,
- CharCodingConfig.DEFAULT,
+ HttpVersionPolicy.FORCE_HTTP_2,
h2Config,
+ H1Config.DEFAULT,
+ CharCodingConfig.DEFAULT,
sslContext));
final ListenerEndpoint listener = listen(new InetSocketAddress(0));
listener.waitFor();
@@ -99,12 +101,13 @@ public class Http2TestServer extends AsyncServer {
}
public InetSocketAddress start(final HttpProcessor httpProcessor, final H1Config h1Config) throws Exception {
- start(new InternalServerHttp1EventHandlerFactory(
+ start(new InternalServerHttp2EventHandlerFactory(
httpProcessor,
handlerRegistry,
+ HttpVersionPolicy.FORCE_HTTP_1,
+ H2Config.DEFAULT,
h1Config,
CharCodingConfig.DEFAULT,
- DefaultConnectionReuseStrategy.INSTANCE,
sslContext));
final ListenerEndpoint listener = listen(new InetSocketAddress(0));
listener.waitFor();
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
index 75a2f62..e32cee7 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp1EventHandlerFactory.java
@@ -27,17 +27,12 @@
package org.apache.hc.core5.testing.nio;
-import java.util.Iterator;
-
import javax.net.ssl.SSLContext;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.ConnectionReuseStrategy;
import org.apache.hc.core5.http.ContentLengthStrategy;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.config.CharCodingConfig;
@@ -50,8 +45,6 @@ import org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler;
import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer;
import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestWriterFactory;
import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseParserFactory;
-import org.apache.hc.core5.http.message.RequestLine;
-import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.NHttpMessageParser;
import org.apache.hc.core5.http.nio.NHttpMessageParserFactory;
import org.apache.hc.core5.http.nio.NHttpMessageWriter;
@@ -120,7 +113,6 @@ class InternalClientHttp1EventHandlerFactory implements IOEventHandlerFactory {
}
final Logger sessionLog = LogManager.getLogger(ioSession.getClass());
final Logger wireLog = LogManager.getLogger("org.apache.hc.core5.http.wire");
- final Logger headerLog = LogManager.getLogger("org.apache.hc.core5.http.headers");
final ClientHttp1StreamDuplexer streamDuplexer = createClientHttp1StreamDuplexer(
new LoggingIOSession(ioSession, sessionLog, wireLog),
httpProcessor,
@@ -131,65 +123,8 @@ class InternalClientHttp1EventHandlerFactory implements IOEventHandlerFactory {
requestWriterFactory.create(),
DefaultContentLengthStrategy.INSTANCE,
DefaultContentLengthStrategy.INSTANCE,
- new ConnectionListener() {
-
- @Override
- public void onConnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " connected");
- }
- }
-
- @Override
- public void onDisconnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " disconnected");
- }
- }
-
- @Override
- public void onError(final HttpConnection connection, final Exception ex) {
- if (ex instanceof ConnectionClosedException) {
- return;
- }
- sessionLog.error(id + " " + ex.getMessage(), ex);
- }
-
- },
- new Http1StreamListener() {
-
- @Override
- public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
- if (headerLog.isDebugEnabled()) {
- headerLog.debug(id + " >> " + new RequestLine(request));
- for (final Iterator<Header> it = request.headerIterator(); it.hasNext(); ) {
- headerLog.debug(id + " >> " + it.next());
- }
- }
- }
-
- @Override
- public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
- if (headerLog.isDebugEnabled()) {
- headerLog.debug(id + " << " + new StatusLine(response));
- for (final Iterator<Header> it = response.headerIterator(); it.hasNext(); ) {
- headerLog.debug(id + " << " + it.next());
- }
- }
- }
-
- @Override
- public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
- if (sessionLog.isDebugEnabled()) {
- if (keepAlive) {
- sessionLog.debug(id + " Connection is kept alive");
- } else {
- sessionLog.debug(id + " Connection is not kept alive");
- }
- }
- }
-
- });
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp1StreamListener(id, InternalHttp1StreamListener.Type.CLIENT, sessionLog));
return new LoggingIOEventHandler(new ClientHttp1IOEventHandler(streamDuplexer), id, sessionLog);
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
index 8f50052..fcbaf8a 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalClientHttp2EventHandlerFactory.java
@@ -29,15 +29,17 @@ package org.apache.hc.core5.testing.nio;
import javax.net.ssl.SSLContext;
-import org.apache.hc.core5.http.ConnectionClosedException;
-import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.config.CharCodingConfig;
-import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.HttpProcessors;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
-import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexer;
+import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexerFactory;
import org.apache.hc.core5.http2.impl.nio.ClientHttpProtocolNegotiator;
import org.apache.hc.core5.reactor.IOEventHandler;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
@@ -50,20 +52,26 @@ class InternalClientHttp2EventHandlerFactory implements IOEventHandlerFactory {
private final HttpProcessor httpProcessor;
private final HandlerFactory<AsyncPushConsumer> exchangeHandlerFactory;
- private final CharCodingConfig charCodingConfig;
+ private final HttpVersionPolicy versionPolicy;
private final H2Config h2Config;
+ private final H1Config h1Config;
+ private final CharCodingConfig charCodingConfig;
private final SSLContext sslContext;
InternalClientHttp2EventHandlerFactory(
final HttpProcessor httpProcessor,
final HandlerFactory<AsyncPushConsumer> exchangeHandlerFactory,
- final CharCodingConfig charCodingConfig,
+ final HttpVersionPolicy versionPolicy,
final H2Config h2Config,
+ final H1Config h1Config,
+ final CharCodingConfig charCodingConfig,
final SSLContext sslContext) {
this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
this.exchangeHandlerFactory = exchangeHandlerFactory;
- this.charCodingConfig = charCodingConfig;
- this.h2Config = h2Config;
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
+ this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ this.h1Config = h1Config != null ? h1Config : H1Config.DEFAULT;
+ this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
this.sslContext = sslContext;
}
@@ -74,40 +82,28 @@ class InternalClientHttp2EventHandlerFactory implements IOEventHandlerFactory {
ioSession.startTls(sslContext, null ,null, null);
}
final Logger sessionLog = LogManager.getLogger(ioSession.getClass());
- return new LoggingIOEventHandler(new ClientHttpProtocolNegotiator(
- ioSession, httpProcessor, exchangeHandlerFactory, charCodingConfig, h2Config,
- new ConnectionListener() {
-
- @Override
- public void onConnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " connected");
- }
- }
-
- @Override
- public void onDisconnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " disconnected");
- }
- }
-
- @Override
- public void onError(final HttpConnection connection, final Exception ex) {
- if (ex instanceof ConnectionClosedException) {
- return;
- }
- sessionLog.error(id + " " + ex.getMessage(), ex);
- }
-
- }, new InternalHttp2StreamListener(id)) {
-
- @Override
- protected ClientHttp2StreamMultiplexer createStreamMultiplexer(final TlsCapableIOSession ioSession) {
- return super.createStreamMultiplexer(new LoggingIOSession(ioSession, sessionLog));
- }
- }, id, sessionLog);
-
+ final LoggingIOSession loggingIOSession = new LoggingIOSession(ioSession, sessionLog);
+ final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory = new ClientHttp1StreamDuplexerFactory(
+ httpProcessor != null ? httpProcessor : HttpProcessors.client(),
+ h1Config,
+ charCodingConfig,
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp1StreamListener(id, InternalHttp1StreamListener.Type.CLIENT, sessionLog));
+ final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientHttp2StreamMultiplexerFactory(
+ httpProcessor != null ? httpProcessor : Http2Processors.client(),
+ exchangeHandlerFactory,
+ h2Config,
+ charCodingConfig,
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp2StreamListener(id));
+ return new LoggingIOEventHandler(
+ new ClientHttpProtocolNegotiator(
+ loggingIOSession,
+ http1StreamHandlerFactory,
+ http2StreamHandlerFactory,
+ versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
+ new InternalConnectionListener(id, sessionLog)),
+ id, sessionLog);
}
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalConnectionListener.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalConnectionListener.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalConnectionListener.java
new file mode 100644
index 0000000..5c0ef96
--- /dev/null
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalConnectionListener.java
@@ -0,0 +1,67 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.testing.nio;
+
+import org.apache.hc.core5.http.ConnectionClosedException;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.logging.log4j.Logger;
+
+class InternalConnectionListener implements ConnectionListener {
+
+ private final String id;
+ private final Logger log;
+
+ public InternalConnectionListener(final String id, final Logger log) {
+ this.log = log;
+ this.id = id;
+ }
+
+ @Override
+ public void onConnect(final HttpConnection connection) {
+ if (log.isDebugEnabled()) {
+ log.debug(id + " " + connection + " connected");
+ }
+ }
+
+ @Override
+ public void onDisconnect(final HttpConnection connection) {
+ if (log.isDebugEnabled()) {
+ log.debug(id + " " + connection + " disconnected");
+ }
+ }
+
+ @Override
+ public void onError(final HttpConnection connection, final Exception ex) {
+ if (ex instanceof ConnectionClosedException) {
+ return;
+ }
+ log.error(id + " " + ex.getMessage(), ex);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalHttp1StreamListener.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalHttp1StreamListener.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalHttp1StreamListener.java
new file mode 100644
index 0000000..48b9608
--- /dev/null
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalHttp1StreamListener.java
@@ -0,0 +1,96 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.testing.nio;
+
+import java.util.Iterator;
+
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
+import org.apache.hc.core5.http.message.RequestLine;
+import org.apache.hc.core5.http.message.StatusLine;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+class InternalHttp1StreamListener implements Http1StreamListener {
+
+ enum Type { CLIENT, SERVER }
+
+ private final String id;
+ private final Type type;
+ private final Logger sessionLog;
+ private final Logger headerLog = LogManager.getLogger("org.apache.hc.core5.http.headers");
+
+ public InternalHttp1StreamListener(final String id, final Type type, final Logger sessionLog) {
+ this.id = id;
+ this.type = type;
+ this.sessionLog = sessionLog;
+ }
+
+ private String requestDirection() {
+ return type == Type.CLIENT ? " >> " : " << ";
+ }
+
+ private String responseDirection() {
+ return type == Type.CLIENT ? " << " : " >> ";
+ }
+
+ @Override
+ public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
+ if (headerLog.isDebugEnabled()) {
+ headerLog.debug(id + requestDirection() + new RequestLine(request));
+ for (final Iterator<Header> it = request.headerIterator(); it.hasNext(); ) {
+ headerLog.debug(id + requestDirection() + it.next());
+ }
+ }
+ }
+
+ @Override
+ public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
+ if (headerLog.isDebugEnabled()) {
+ headerLog.debug(id + responseDirection() + new StatusLine(response));
+ for (final Iterator<Header> it = response.headerIterator(); it.hasNext(); ) {
+ headerLog.debug(id + responseDirection() + it.next());
+ }
+ }
+ }
+
+ @Override
+ public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
+ if (sessionLog.isDebugEnabled()) {
+ if (keepAlive) {
+ sessionLog.debug(id + " Connection is kept alive");
+ } else {
+ sessionLog.debug(id + " Connection is not kept alive");
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
index a051d51..bf1ad15 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp1EventHandlerFactory.java
@@ -27,17 +27,12 @@
package org.apache.hc.core5.testing.nio;
-import java.util.Iterator;
-
import javax.net.ssl.SSLContext;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.ConnectionReuseStrategy;
import org.apache.hc.core5.http.ContentLengthStrategy;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.config.CharCodingConfig;
@@ -50,8 +45,6 @@ import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestParserFactory;
import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseWriterFactory;
import org.apache.hc.core5.http.impl.nio.ServerHttp1IOEventHandler;
import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexer;
-import org.apache.hc.core5.http.message.RequestLine;
-import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.nio.NHttpMessageParser;
@@ -125,7 +118,6 @@ class InternalServerHttp1EventHandlerFactory implements IOEventHandlerFactory {
}
final Logger sessionLog = LogManager.getLogger(ioSession.getClass());
final Logger wireLog = LogManager.getLogger("org.apache.hc.core5.http.wire");
- final Logger headerLog = LogManager.getLogger("org.apache.hc.core5.http.headers");
final ServerHttp1StreamDuplexer streamDuplexer = createServerHttp1StreamDuplexer(
new LoggingIOSession(ioSession, sessionLog, wireLog),
@@ -138,65 +130,8 @@ class InternalServerHttp1EventHandlerFactory implements IOEventHandlerFactory {
responseWriterFactory.create(),
DefaultContentLengthStrategy.INSTANCE,
DefaultContentLengthStrategy.INSTANCE,
- new ConnectionListener() {
-
- @Override
- public void onConnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " connected");
- }
- }
-
- @Override
- public void onDisconnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " disconnected");
- }
- }
-
- @Override
- public void onError(final HttpConnection connection, final Exception ex) {
- if (ex instanceof ConnectionClosedException) {
- return;
- }
- sessionLog.error(id + " " + ex.getMessage(), ex);
- }
-
- },
- new Http1StreamListener() {
-
- @Override
- public void onRequestHead(final HttpConnection connection, final HttpRequest request) {
- if (headerLog.isDebugEnabled()) {
- headerLog.debug(id + " << " + new RequestLine(request));
- for (final Iterator<Header> it = request.headerIterator(); it.hasNext(); ) {
- headerLog.debug(id + " << " + it.next());
- }
- }
- }
-
- @Override
- public void onResponseHead(final HttpConnection connection, final HttpResponse response) {
- if (headerLog.isDebugEnabled()) {
- headerLog.debug(id + " >> " + new StatusLine(response));
- for (final Iterator<Header> it = response.headerIterator(); it.hasNext(); ) {
- headerLog.debug(id + " >> " + it.next());
- }
- }
- }
-
- @Override
- public void onExchangeComplete(final HttpConnection connection, final boolean keepAlive) {
- if (sessionLog.isDebugEnabled()) {
- if (keepAlive) {
- sessionLog.debug(id + " Connection is kept alive");
- } else {
- sessionLog.debug(id + " Connection is not kept alive");
- }
- }
- }
-
- });
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp1StreamListener(id, InternalHttp1StreamListener.Type.SERVER, sessionLog));
return new LoggingIOEventHandler(new ServerHttp1IOEventHandler(streamDuplexer), id, sessionLog);
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
index bed94ed..4a69374 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/InternalServerHttp2EventHandlerFactory.java
@@ -29,15 +29,17 @@ package org.apache.hc.core5.testing.nio;
import javax.net.ssl.SSLContext;
-import org.apache.hc.core5.http.ConnectionClosedException;
-import org.apache.hc.core5.http.HttpConnection;
import org.apache.hc.core5.http.config.CharCodingConfig;
-import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.config.H1Config;
+import org.apache.hc.core5.http.impl.HttpProcessors;
+import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
-import org.apache.hc.core5.http2.impl.nio.ServerHttp2StreamMultiplexer;
+import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.ServerHttp2StreamMultiplexerFactory;
import org.apache.hc.core5.http2.impl.nio.ServerHttpProtocolNegotiator;
import org.apache.hc.core5.reactor.IOEventHandler;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
@@ -50,20 +52,26 @@ class InternalServerHttp2EventHandlerFactory implements IOEventHandlerFactory {
private final HttpProcessor httpProcessor;
private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
- private final CharCodingConfig charCodingConfig;
+ private final HttpVersionPolicy versionPolicy;
private final H2Config h2Config;
+ private final H1Config h1Config;
+ private final CharCodingConfig charCodingConfig;
private final SSLContext sslContext;
public InternalServerHttp2EventHandlerFactory(
final HttpProcessor httpProcessor,
final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
- final CharCodingConfig charCodingConfig,
+ final HttpVersionPolicy versionPolicy,
final H2Config h2Config,
+ final H1Config h1Config,
+ final CharCodingConfig charCodingConfig,
final SSLContext sslContext) {
this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
- this.charCodingConfig = charCodingConfig;
- this.h2Config = h2Config;
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
+ this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ this.h1Config = h1Config != null ? h1Config : H1Config.DEFAULT;
+ this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
this.sslContext = sslContext;
}
@@ -74,39 +82,29 @@ class InternalServerHttp2EventHandlerFactory implements IOEventHandlerFactory {
ioSession.startTls(sslContext, null ,null, null);
}
final Logger sessionLog = LogManager.getLogger(ioSession.getClass());
- return new LoggingIOEventHandler(new ServerHttpProtocolNegotiator(
- ioSession, httpProcessor, exchangeHandlerFactory, charCodingConfig, h2Config,
- new ConnectionListener() {
-
- @Override
- public void onConnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " connected");
- }
- }
-
- @Override
- public void onDisconnect(final HttpConnection connection) {
- if (sessionLog.isDebugEnabled()) {
- sessionLog.debug(id + " " + connection + " disconnected");
- }
- }
-
- @Override
- public void onError(final HttpConnection connection, final Exception ex) {
- if (ex instanceof ConnectionClosedException) {
- return;
- }
- sessionLog.error(id + " " + ex.getMessage(), ex);
- }
-
- }, new InternalHttp2StreamListener(id)) {
-
- @Override
- protected ServerHttp2StreamMultiplexer createStreamMultiplexer(final TlsCapableIOSession ioSession) {
- return super.createStreamMultiplexer(new LoggingIOSession(ioSession, sessionLog));
- }
- }, id, sessionLog);
-
+ final LoggingIOSession loggingIOSession = new LoggingIOSession(ioSession, sessionLog);
+ final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory = new ServerHttp1StreamDuplexerFactory(
+ httpProcessor != null ? httpProcessor : HttpProcessors.server(),
+ exchangeHandlerFactory,
+ h1Config,
+ charCodingConfig,
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp1StreamListener(id, InternalHttp1StreamListener.Type.SERVER, sessionLog));
+ final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory = new ServerHttp2StreamMultiplexerFactory(
+ httpProcessor != null ? httpProcessor : Http2Processors.server(),
+ exchangeHandlerFactory,
+ h2Config,
+ charCodingConfig,
+ new InternalConnectionListener(id, sessionLog),
+ new InternalHttp2StreamListener(id));
+ return new LoggingIOEventHandler(
+ new ServerHttpProtocolNegotiator(
+ loggingIOSession,
+ http1StreamHandlerFactory,
+ http2StreamHandlerFactory,
+ versionPolicy,
+ new InternalConnectionListener(id, sessionLog)),
+ id, sessionLog);
}
+
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
index 096c03f..5ddefe0 100644
--- a/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
+++ b/httpcore5-testing/src/main/java/org/apache/hc/core5/testing/nio/LoggingIOSession.java
@@ -34,7 +34,6 @@ import java.nio.channels.ByteChannel;
import java.nio.channels.SelectionKey;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.reactor.Command;
@@ -43,6 +42,7 @@ import org.apache.hc.core5.reactor.TlsCapableIOSession;
import org.apache.hc.core5.reactor.ssl.SSLBufferManagement;
import org.apache.hc.core5.reactor.ssl.SSLSessionInitializer;
import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.testing.classic.Wire;
import org.apache.logging.log4j.Logger;
public class LoggingIOSession implements TlsCapableIOSession {
@@ -197,6 +197,11 @@ public class LoggingIOSession implements TlsCapableIOSession {
}
@Override
+ public TlsDetails getTlsDetails() {
+ return session.getTlsDetails();
+ }
+
+ @Override
public void startTls(
final SSLContext sslContext,
final SSLBufferManagement sslBufferManagement,
@@ -206,11 +211,6 @@ public class LoggingIOSession implements TlsCapableIOSession {
}
@Override
- public SSLSession getSSLSession() {
- return session.getSSLSession();
- }
-
- @Override
public String toString() {
return this.session.toString();
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/SSLTestContexts.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/SSLTestContexts.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/SSLTestContexts.java
new file mode 100644
index 0000000..6668f7a
--- /dev/null
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/SSLTestContexts.java
@@ -0,0 +1,55 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.testing;
+
+import java.net.URL;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.hc.core5.ssl.SSLContextBuilder;
+
+public final class SSLTestContexts {
+
+ public static SSLContext createServerSSLContext() throws Exception {
+ final URL keyStoreURL = SSLTestContexts.class.getResource("/test.keystore");
+ final String storePassword = "nopassword";
+ return SSLContextBuilder.create()
+ .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
+ .loadKeyMaterial(keyStoreURL, storePassword.toCharArray(), storePassword.toCharArray())
+ .build();
+ }
+
+ public static SSLContext createClientSSLContext() throws Exception {
+ final URL keyStoreURL = SSLTestContexts.class.getResource("/test.keystore");
+ final String storePassword = "nopassword";
+ return SSLContextBuilder.create()
+ .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
+ .build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
index 6e0af70..2d0430a 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
@@ -124,6 +124,7 @@ import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.SessionRequest;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
import org.apache.hc.core5.testing.ProtocolScheme;
+import org.apache.hc.core5.testing.SSLTestContexts;
import org.apache.hc.core5.util.CharArrayBuffer;
import org.apache.hc.core5.util.TextUtils;
import org.apache.hc.core5.util.TimeValue;
@@ -158,7 +159,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
public void setup() throws Exception {
client = new Http1TestClient(
IOReactorConfig.DEFAULT,
- scheme == ProtocolScheme.HTTPS ? createClientSSLContext() : null);
+ scheme == ProtocolScheme.HTTPS ? SSLTestContexts.createClientSSLContext() : null);
}
@After
@@ -1353,7 +1354,7 @@ public class Http1IntegrationTest extends InternalHttp1ServerTestBase {
H1Config.DEFAULT,
CharCodingConfig.DEFAULT,
DefaultConnectionReuseStrategy.INSTANCE,
- scheme == ProtocolScheme.HTTPS ? createServerSSLContext() : null) {
+ scheme == ProtocolScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null) {
@Override
protected ServerHttp1StreamDuplexer createServerHttp1StreamDuplexer(
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
index b67f8d9..438e6db 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2IntegrationTest.java
@@ -111,6 +111,7 @@ import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.SessionRequest;
import org.apache.hc.core5.testing.ProtocolScheme;
+import org.apache.hc.core5.testing.SSLTestContexts;
import org.apache.hc.core5.util.TextUtils;
import org.apache.hc.core5.util.TimeValue;
import org.hamcrest.CoreMatchers;
@@ -144,7 +145,7 @@ public class Http2IntegrationTest extends InternalHttp2ServerTestBase {
@Before
public void setup() throws Exception {
client = new Http2TestClient(IOReactorConfig.DEFAULT,
- scheme == ProtocolScheme.HTTPS ? createClientSSLContext() : null);
+ scheme == ProtocolScheme.HTTPS ? SSLTestContexts.createClientSSLContext() : null);
}
@After
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ProtocolNegotiationTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ProtocolNegotiationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ProtocolNegotiationTest.java
new file mode 100644
index 0000000..4fe5b0e
--- /dev/null
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ProtocolNegotiationTest.java
@@ -0,0 +1,251 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.testing.nio;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.concurrent.Future;
+
+import org.apache.hc.core5.function.Supplier;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpResponse;
+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.ProtocolVersion;
+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;
+import org.apache.hc.core5.http.nio.BasicRequestProducer;
+import org.apache.hc.core5.http.nio.BasicResponseConsumer;
+import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2RequesterBootstrap;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2ServerBootstrap;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.Http2AsyncRequester;
+import org.apache.hc.core5.http2.ssl.H2ClientTlsStrategy;
+import org.apache.hc.core5.http2.ssl.H2ServerTlsStrategy;
+import org.apache.hc.core5.http2.ssl.SecurePortStrategy;
+import org.apache.hc.core5.io.ShutdownType;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.reactor.ListenerEndpoint;
+import org.apache.hc.core5.testing.SSLTestContexts;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.logging.log4j.LogManager;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+
+public class Http2ProtocolNegotiationTest {
+
+ private static final TimeValue TIMEOUT = TimeValue.ofSeconds(30);
+
+ private HttpAsyncServer server;
+
+ @Rule
+ public ExternalResource serverResource = new ExternalResource() {
+
+ @Override
+ protected void before() throws Throwable {
+ server = H2ServerBootstrap.bootstrap()
+ .setTlsStrategy(new H2ServerTlsStrategy(SSLTestContexts.createServerSSLContext(), new SecurePortStrategy() {
+
+ @Override
+ public boolean isSecure(final SocketAddress localAddress) {
+ return true;
+ }
+
+ }))
+ .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
+ .setIOReactorConfig(
+ IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build())
+ .register("*", new Supplier<AsyncServerExchangeHandler>() {
+
+ @Override
+ public AsyncServerExchangeHandler get() {
+ return new EchoHandler(2048);
+ }
+
+ })
+ .setConnectionListener(new InternalConnectionListener("test", LogManager.getLogger(getClass())))
+ .create();
+ }
+
+ @Override
+ protected void after() {
+ if (server != null) {
+ try {
+ server.shutdown(ShutdownType.IMMEDIATE);
+ server = null;
+ } catch (final Exception ignore) {
+ }
+ }
+ }
+
+ };
+
+ private Http2AsyncRequester requester;
+
+ @Rule
+ public ExternalResource clientResource = new ExternalResource() {
+
+ @Override
+ protected void before() throws Throwable {
+ requester = H2RequesterBootstrap.bootstrap()
+ .setTlsStrategy(new H2ClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
+ .setIOReactorConfig(IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build())
+ .create();
+ }
+
+ @Override
+ protected void after() {
+ if (requester != null) {
+ try {
+ requester.shutdown(ShutdownType.IMMEDIATE);
+ requester = null;
+ } catch (final Exception ignore) {
+ }
+ }
+ }
+
+ };
+
+ private static int version;
+
+ @BeforeClass
+ public static void determineJavaVersion() {
+ version = 7;
+ final String s = System.getProperty("java.version");
+ if (s.equals("9-ea")) {
+ version = 9;
+ }
+ final String[] parts = s.split("\\.");
+ if (parts.length >= 2) {
+ if (parts[0].equals("1")) {
+ try {
+ version = Integer.parseInt(parts[1]);
+ } catch (NumberFormatException ignore) {
+ }
+ }
+ }
+ }
+
+ @Before
+ public void checkVersion() {
+ Assume.assumeTrue("Java version must be 1.8 or greater", version > 7);
+ }
+
+ @Test
+ public void testForceHttp1() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+ final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_1, null);
+ final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+
+ final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message1, CoreMatchers.notNullValue());
+ final HttpResponse response1 = message1.getHead();
+ Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ Assert.assertThat(response1.getVersion(), CoreMatchers.<ProtocolVersion>equalTo(HttpVersion.HTTP_1_1));
+ }
+
+ @Test
+ public void testForceHttp2() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+ final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.FORCE_HTTP_2, null);
+ final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+
+ final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message1, CoreMatchers.notNullValue());
+ final HttpResponse response1 = message1.getHead();
+ Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ Assert.assertThat(response1.getVersion(), CoreMatchers.<ProtocolVersion>equalTo(HttpVersion.HTTP_2));
+ }
+
+ @Test
+ public void testNegotiateProtocol() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort(), "https");
+ final Future<AsyncClientEndpoint> connectFuture = requester.connect(target, TIMEOUT, HttpVersionPolicy.NEGOTIATE, null);
+ final AsyncClientEndpoint endpoint = connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+
+ final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message1, CoreMatchers.notNullValue());
+ final HttpResponse response1 = message1.getHead();
+ Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+
+ if (version < 9) {
+ Assert.assertThat(response1.getVersion(), CoreMatchers.<ProtocolVersion>equalTo(HttpVersion.HTTP_1_1));
+ } else {
+// Assert.assertThat("Requires --add-opens java.base/sun.security.ssl=ALL-UNNAMED with Java 1.9+ " +
+// " in order to enable reflective access to SSLEngine",
+// response1.getVersion(), CoreMatchers.<ProtocolVersion>equalTo(HttpVersion.HTTP_2));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ServerAndRequesterTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ServerAndRequesterTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ServerAndRequesterTest.java
new file mode 100644
index 0000000..1b01ee8
--- /dev/null
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ServerAndRequesterTest.java
@@ -0,0 +1,288 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.testing.nio;
+
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.Future;
+
+import org.apache.hc.core5.function.Supplier;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpHost;
+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.impl.bootstrap.HttpAsyncRequester;
+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;
+import org.apache.hc.core5.http.nio.BasicRequestProducer;
+import org.apache.hc.core5.http.nio.BasicResponseConsumer;
+import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.http.nio.entity.StringAsyncEntityProducer;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2RequesterBootstrap;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2ServerBootstrap;
+import org.apache.hc.core5.io.ShutdownType;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.reactor.ListenerEndpoint;
+import org.apache.hc.core5.util.TimeValue;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExternalResource;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class Http2ServerAndRequesterTest {
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> protocols() {
+ return Arrays.asList(new Object[][]{
+ { HttpVersionPolicy.NEGOTIATE },
+ { HttpVersionPolicy.FORCE_HTTP_1 },
+ { HttpVersionPolicy.FORCE_HTTP_2 }
+ });
+ }
+
+ private static final TimeValue TIMEOUT = TimeValue.ofSeconds(30);
+
+ private final HttpVersionPolicy versionPolicy;
+
+ public Http2ServerAndRequesterTest(final HttpVersionPolicy versionPolicy) {
+ this.versionPolicy = versionPolicy;
+ }
+
+ private HttpAsyncServer server;
+
+ @Rule
+ public ExternalResource serverResource = new ExternalResource() {
+
+ @Override
+ protected void before() throws Throwable {
+ server = H2ServerBootstrap.bootstrap()
+ .setVersionPolicy(versionPolicy)
+ .setIOReactorConfig(
+ IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build())
+ .register("*", new Supplier<AsyncServerExchangeHandler>() {
+
+ @Override
+ public AsyncServerExchangeHandler get() {
+ return new EchoHandler(2048);
+ }
+
+ })
+ .create();
+ }
+
+ @Override
+ protected void after() {
+ if (server != null) {
+ try {
+ server.shutdown(ShutdownType.IMMEDIATE);
+ server = null;
+ } catch (final Exception ignore) {
+ }
+ }
+ }
+
+ };
+
+ private HttpAsyncRequester requester;
+
+ @Rule
+ public ExternalResource clientResource = new ExternalResource() {
+
+ @Override
+ protected void before() throws Throwable {
+ requester = H2RequesterBootstrap.bootstrap()
+ .setVersionPolicy(versionPolicy)
+ .setIOReactorConfig(IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build())
+ .create();
+ }
+
+ @Override
+ protected void after() {
+ if (requester != null) {
+ try {
+ requester.shutdown(ShutdownType.IMMEDIATE);
+ requester = null;
+ } catch (final Exception ignore) {
+ }
+ }
+ }
+
+ };
+
+ @Test
+ public void testSequentialRequests() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort());
+ final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
+ final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message1, CoreMatchers.notNullValue());
+ final HttpResponse response1 = message1.getHead();
+ Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body1 = message1.getBody();
+ Assert.assertThat(body1, CoreMatchers.equalTo("some stuff"));
+
+ final Future<Message<HttpResponse, String>> resultFuture2 = requester.execute(
+ new BasicRequestProducer("POST", target, "/other-stuff",
+ new StringAsyncEntityProducer("some other stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
+ final Message<HttpResponse, String> message2 = resultFuture2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message2, CoreMatchers.notNullValue());
+ final HttpResponse response2 = message2.getHead();
+ Assert.assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body2 = message2.getBody();
+ Assert.assertThat(body2, CoreMatchers.equalTo("some other stuff"));
+
+ final Future<Message<HttpResponse, String>> resultFuture3 = requester.execute(
+ new BasicRequestProducer("POST", target, "/more-stuff",
+ new StringAsyncEntityProducer("some more stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
+ final Message<HttpResponse, String> message3 = resultFuture3.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message3, CoreMatchers.notNullValue());
+ final HttpResponse response3 = message3.getHead();
+ Assert.assertThat(response3.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body3 = message3.getBody();
+ Assert.assertThat(body3, CoreMatchers.equalTo("some more stuff"));
+ }
+
+ @Test
+ public void testSequentialRequestsSameEndpoint() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort());
+ final Future<AsyncClientEndpoint> endpointFuture = requester.connect(target, TimeValue.ofSeconds(5));
+ final AsyncClientEndpoint endpoint = endpointFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ try {
+
+ final Future<Message<HttpResponse, String>> resultFuture1 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message1 = resultFuture1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message1, CoreMatchers.notNullValue());
+ final HttpResponse response1 = message1.getHead();
+ Assert.assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body1 = message1.getBody();
+ Assert.assertThat(body1, CoreMatchers.equalTo("some stuff"));
+
+ final Future<Message<HttpResponse, String>> resultFuture2 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/other-stuff",
+ new StringAsyncEntityProducer("some other stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message2 = resultFuture2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message2, CoreMatchers.notNullValue());
+ final HttpResponse response2 = message2.getHead();
+ Assert.assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body2 = message2.getBody();
+ Assert.assertThat(body2, CoreMatchers.equalTo("some other stuff"));
+
+ final Future<Message<HttpResponse, String>> resultFuture3 = endpoint.execute(
+ new BasicRequestProducer("POST", target, "/more-stuff",
+ new StringAsyncEntityProducer("some more stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null);
+ final Message<HttpResponse, String> message3 = resultFuture3.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message3, CoreMatchers.notNullValue());
+ final HttpResponse response3 = message3.getHead();
+ Assert.assertThat(response3.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body3 = message3.getBody();
+ Assert.assertThat(body3, CoreMatchers.equalTo("some more stuff"));
+
+ } finally {
+ endpoint.releaseAndReuse();
+ }
+ }
+
+ @Test
+ public void testPipelinedRequests() throws Exception {
+ server.start();
+ final ListenerEndpoint listener = server.listen(new InetSocketAddress(0));
+ listener.waitFor();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort());
+ final Future<AsyncClientEndpoint> endpointFuture = requester.connect(target, TimeValue.ofSeconds(5));
+ final AsyncClientEndpoint endpoint = endpointFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ try {
+
+ final Queue<Future<Message<HttpResponse, String>>> queue = new LinkedList<>();
+
+ queue.add(endpoint.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null));
+ queue.add(endpoint.execute(
+ new BasicRequestProducer("POST", target, "/other-stuff",
+ new StringAsyncEntityProducer("some other stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null));
+ queue.add(endpoint.execute(
+ new BasicRequestProducer("POST", target, "/more-stuff",
+ new StringAsyncEntityProducer("some more stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), null));
+
+ while (!queue.isEmpty()) {
+ final Future<Message<HttpResponse, String>> resultFuture = queue.remove();
+ final Message<HttpResponse, String> message = resultFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ Assert.assertThat(message, CoreMatchers.notNullValue());
+ final HttpResponse response = message.getHead();
+ Assert.assertThat(response.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
+ final String body = message.getBody();
+ Assert.assertThat(body, CoreMatchers.containsString("stuff"));
+ }
+
+ } finally {
+ endpoint.releaseAndReuse();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp1ServerTestBase.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp1ServerTestBase.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp1ServerTestBase.java
index c63f510..94081f6 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp1ServerTestBase.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp1ServerTestBase.java
@@ -27,13 +27,9 @@
package org.apache.hc.core5.testing.nio;
-import java.net.URL;
-
-import javax.net.ssl.SSLContext;
-
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.testing.ProtocolScheme;
+import org.apache.hc.core5.testing.SSLTestContexts;
import org.apache.hc.core5.util.TimeValue;
import org.junit.Rule;
import org.junit.rules.ExternalResource;
@@ -59,7 +55,7 @@ public abstract class InternalHttp1ServerTestBase {
protected void before() throws Throwable {
server = new Http1TestServer(
IOReactorConfig.DEFAULT,
- scheme == ProtocolScheme.HTTPS ? createServerSSLContext() : null);
+ scheme == ProtocolScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null);
}
@Override
@@ -75,21 +71,4 @@ public abstract class InternalHttp1ServerTestBase {
};
- protected SSLContext createServerSSLContext() throws Exception {
- final URL keyStoreURL = getClass().getResource("/test.keystore");
- final String storePassword = "nopassword";
- return SSLContextBuilder.create()
- .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
- .loadKeyMaterial(keyStoreURL, storePassword.toCharArray(), storePassword.toCharArray())
- .build();
- }
-
- protected SSLContext createClientSSLContext() throws Exception {
- final URL keyStoreURL = getClass().getResource("/test.keystore");
- final String storePassword = "nopassword";
- return SSLContextBuilder.create()
- .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
- .build();
- }
-
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp2ServerTestBase.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp2ServerTestBase.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp2ServerTestBase.java
index 7d49753..c2f0e28 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp2ServerTestBase.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/InternalHttp2ServerTestBase.java
@@ -27,13 +27,9 @@
package org.apache.hc.core5.testing.nio;
-import java.net.URL;
-
-import javax.net.ssl.SSLContext;
-
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.testing.ProtocolScheme;
+import org.apache.hc.core5.testing.SSLTestContexts;
import org.apache.hc.core5.util.TimeValue;
import org.junit.Rule;
import org.junit.rules.ExternalResource;
@@ -58,7 +54,7 @@ public abstract class InternalHttp2ServerTestBase {
@Override
protected void before() throws Throwable {
server = new Http2TestServer(IOReactorConfig.DEFAULT,
- scheme == ProtocolScheme.HTTPS ? createServerSSLContext() : null);
+ scheme == ProtocolScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null);
}
@Override
@@ -74,21 +70,4 @@ public abstract class InternalHttp2ServerTestBase {
};
- protected SSLContext createServerSSLContext() throws Exception {
- final URL keyStoreURL = getClass().getResource("/test.keystore");
- final String storePassword = "nopassword";
- return SSLContextBuilder.create()
- .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
- .loadKeyMaterial(keyStoreURL, storePassword.toCharArray(), storePassword.toCharArray())
- .build();
- }
-
- protected SSLContext createClientSSLContext() throws Exception {
- final URL keyStoreURL = getClass().getResource("/test.keystore");
- final String storePassword = "nopassword";
- return SSLContextBuilder.create()
- .loadTrustMaterial(keyStoreURL, storePassword.toCharArray())
- .build();
- }
-
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java b/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
index 42d12ff..0f0c787 100644
--- a/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
+++ b/httpcore5/src/examples/org/apache/hc/core5/http/examples/AsyncReverseProxyExample.java
@@ -313,7 +313,7 @@ public class AsyncReverseProxyExample {
System.out.println("[proxy->origin] " + exchangeState.id + " request connection to " + targetHost);
- requester.connect(targetHost, TimeValue.ofSeconds(30), new FutureCallback<AsyncClientEndpoint>() {
+ requester.connect(targetHost, TimeValue.ofSeconds(30), null, new FutureCallback<AsyncClientEndpoint>() {
@Override
public void completed(final AsyncClientEndpoint clientEndpoint) {
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequester.java
----------------------------------------------------------------------
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequester.java
index 94c92d5..f0da106 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/AsyncRequester.java
@@ -72,13 +72,14 @@ public class AsyncRequester extends IOReactorExecutor<DefaultConnectingIOReactor
return new InetSocketAddress(hostName, port);
}
- protected SessionRequest requestSession(
+ public SessionRequest requestSession(
final HttpHost host,
final TimeValue timeout,
+ final Object attachment,
final SessionRequestCallback callback) {
Args.notNull(host, "Host");
Args.notNull(timeout, "Timeout");
- final SessionRequest sessionRequest = reactor().connect(host, toSocketAddress(host), null, null, callback);
+ final SessionRequest sessionRequest = reactor().connect(host, toSocketAddress(host), null, attachment, callback);
sessionRequest.setConnectTimeout(timeout.toMillisIntBound());
return sessionRequest;
}