diff --git a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java index dad32dc8222..f0388955387 100644 --- a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java +++ b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java @@ -137,7 +137,18 @@ public class HTTP2Client extends ContainerLifeCycle setByteBufferPool(new MappedByteBufferPool()); if (connectionFactory == null) - setClientConnectionFactory(new HTTP2ClientConnectionFactory()); + { + HTTP2ClientConnectionFactory h2 = new HTTP2ClientConnectionFactory(); + ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), h2, getProtocols()); + setClientConnectionFactory((endPoint, context) -> + { + ClientConnectionFactory factory = h2; + SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY); + if (sslContextFactory != null) + factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn); + return factory.newConnection(endPoint, context); + }); + } if (sessions == null) { @@ -356,17 +367,7 @@ public class HTTP2Client extends ContainerLifeCycle context.put(HTTP2ClientConnectionFactory.BYTE_BUFFER_POOL_CONTEXT_KEY, getByteBufferPool()); context.put(HTTP2ClientConnectionFactory.EXECUTOR_CONTEXT_KEY, getExecutor()); context.put(HTTP2ClientConnectionFactory.SCHEDULER_CONTEXT_KEY, getScheduler()); - - ClientConnectionFactory factory = getClientConnectionFactory(); - - SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY); - if (sslContextFactory != null) - { - ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), factory, getProtocols()); - factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn); - } - - return factory.newConnection(endpoint, context); + return getClientConnectionFactory().newConnection(endpoint, context); } @Override diff --git a/jetty-http2/http2-http-client-transport/pom.xml b/jetty-http2/http2-http-client-transport/pom.xml index be073c272d9..df28dd82e04 100644 --- a/jetty-http2/http2-http-client-transport/pom.xml +++ b/jetty-http2/http2-http-client-transport/pom.xml @@ -15,6 +15,38 @@ + + + maven-dependency-plugin + + + copy + generate-resources + + copy + + + + + org.mortbay.jetty.alpn + alpn-boot + ${alpn.version} + jar + false + ${project.build.directory}/alpn + + + + + + + + maven-surefire-plugin + + -Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar + + + diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java index 82e4ba3f92f..ea16c18feaf 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java @@ -22,19 +22,24 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.util.Map; +import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClientTransport; import org.eclipse.jetty.client.HttpDestination; import org.eclipse.jetty.client.Origin; import org.eclipse.jetty.client.api.Connection; +import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.client.HTTP2Client; +import org.eclipse.jetty.http2.client.HTTP2ClientConnectionFactory; import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.ssl.SslClientConnectionFactory; import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.ContainerLifeCycle; +import org.eclipse.jetty.util.ssl.SslContextFactory; @ManagedObject("The HTTP/2 client transport") public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements HttpClientTransport @@ -68,7 +73,7 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements addBean(client); super.doStart(); - this.connectionFactory = client.getClientConnectionFactory(); + this.connectionFactory = new HTTP2ClientConnectionFactory(); client.setClientConnectionFactory((endPoint, context) -> { HttpDestination destination = (HttpDestination)context.get(HTTP_DESTINATION_CONTEXT_KEY); @@ -128,13 +133,21 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements } }; - client.connect(httpClient.getSslContextFactory(), address, listener, promise, context); + SslContextFactory sslContextFactory = null; + if (HttpScheme.HTTPS.is(destination.getScheme())) + sslContextFactory = httpClient.getSslContextFactory(); + + client.connect(sslContextFactory, address, listener, promise, context); } @Override public org.eclipse.jetty.io.Connection newConnection(EndPoint endPoint, Map context) throws IOException { - return connectionFactory.newConnection(endPoint, context); + ClientConnectionFactory factory = connectionFactory; + SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY); + if (sslContextFactory != null) + factory = new ALPNClientConnectionFactory(client.getExecutor(), factory, client.getProtocols()); + return factory.newConnection(endPoint, context); } protected HttpConnectionOverHTTP2 newHttpConnection(HttpDestination destination, Session session) diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index 40f322098cd..7a061eca852 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -21,9 +21,13 @@ package org.eclipse.jetty.http2.client.http; import java.util.concurrent.Executor; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http2.client.HTTP2Client; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; public class HttpClientTransportOverHTTP2Test @@ -51,4 +55,24 @@ public class HttpClientTransportOverHTTP2Test Assert.assertTrue(http2Client.isStopped()); } + + @Ignore + @Test + public void testExternalServer() throws Exception + { + HTTP2Client http2Client = new HTTP2Client(); + SslContextFactory sslContextFactory = new SslContextFactory(); + HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory); + Executor executor = new QueuedThreadPool(); + httpClient.setExecutor(executor); + + httpClient.start(); + +// ContentResponse response = httpClient.GET("https://http2.akamai.com/"); + ContentResponse response = httpClient.GET("https://webtide.com/"); + + Assert.assertEquals(HttpStatus.OK_200, response.getStatus()); + + httpClient.stop(); + } } diff --git a/jetty-http2/http2-http-client-transport/src/test/resources/jetty-logging.properties b/jetty-http2/http2-http-client-transport/src/test/resources/jetty-logging.properties new file mode 100644 index 00000000000..287d28319e0 --- /dev/null +++ b/jetty-http2/http2-http-client-transport/src/test/resources/jetty-logging.properties @@ -0,0 +1,5 @@ +org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog +#org.eclipse.jetty.client.LEVEL=DEBUG +org.eclipse.jetty.http2.hpack.LEVEL=INFO +#org.eclipse.jetty.http2.LEVEL=DEBUG +#org.eclipse.jetty.io.ssl.LEVEL=DEBUG diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java index b213a5b0285..1ae1a7a0c33 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java @@ -84,29 +84,42 @@ public abstract class AbstractConnection implements Connection protected void failedCallback(final Callback callback, final Throwable x) { - // TODO always dispatch failure ? - try + if (callback.isNonBlocking()) { - getExecutor().execute(new Runnable() + try { - @Override - public void run() - { - try - { - callback.failed(x); - } - catch (Exception e) - { - LOG.warn(e); - } - } - }); + callback.failed(x); + } + catch (Exception e) + { + LOG.warn(e); + } } - catch(RejectedExecutionException e) + else { - LOG.debug(e); - callback.failed(x); + try + { + getExecutor().execute(new Runnable() + { + @Override + public void run() + { + try + { + callback.failed(x); + } + catch (Exception e) + { + LOG.warn(e); + } + } + }); + } + catch(RejectedExecutionException e) + { + LOG.debug(e); + callback.failed(x); + } } } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java index 73acb763aaf..0444f788aba 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java @@ -216,8 +216,8 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint isOpen()?"Open":"CLOSED", isInputShutdown()?"ISHUT":"in", isOutputShutdown()?"OSHUT":"out", - _fillInterest.isInterested()?"R":"-", - _writeFlusher.isInProgress()?"W":"-", + _fillInterest.toStateString(), + _writeFlusher.toStateString(), getIdleFor(), getIdleTimeout(), getConnection()==null?null:getConnection().getClass().getSimpleName()); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java b/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java index 4eff032a8ab..b5c48c4b088 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/FillInterest.java @@ -138,7 +138,13 @@ public abstract class FillInterest @Override public String toString() { - return String.format("FillInterest@%x{%b,%s}", hashCode(), _interested.get(), _interested.get()); + return String.format("FillInterest@%x{%b,%s}", hashCode(), _interested.get()!=null, _interested.get()); + } + + + public String toStateString() + { + return _interested.get()==null?"-":"FI"; } /** diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java index 612fa5603d0..f2dea7d8c36 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java @@ -522,4 +522,23 @@ abstract public class WriteFlusher { return String.format("WriteFlusher@%x{%s}", hashCode(), _state.get()); } + + public String toStateString() + { + switch(_state.get().getType()) + { + case WRITING: + return "W"; + case PENDING: + return "P"; + case COMPLETING: + return "C"; + case IDLE: + return "-"; + case FAILED: + return "F"; + default: + return "?"; + } + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 0c8a463c67c..d92cb3a03ea 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -2435,25 +2435,6 @@ public class Request implements HttpServletRequest @Override public T upgrade(Class handlerClass) throws IOException, ServletException { - if (getContext() == null) - throw new ServletException ("Unable to instantiate "+handlerClass); - - try - { - //Instantiate an instance and inject it - T h = getContext().createInstance(handlerClass); - - //TODO handle the rest of the upgrade process - - return h; - } - catch (Exception e) - { - if (e instanceof ServletException) - throw (ServletException)e; - throw new ServletException(e); - } + throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty"); } - - } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java index 42b7086d4cc..1ae25d8a668 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java @@ -73,6 +73,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope private static final Logger LOG = Log.getLogger(ServletHolder.class); private int _initOrder = -1; private boolean _initOnStartup=false; + private boolean _initialized = false; private Map _roleMap; private String _forcedPath; private String _runAsRole; @@ -81,7 +82,6 @@ public class ServletHolder extends Holder implements UserIdentity.Scope private ServletRegistration.Dynamic _registration; private JspContainer _jspContainer; - private transient Servlet _servlet; private transient Config _config; private transient long _unavailable; @@ -396,21 +396,24 @@ public class ServletHolder extends Holder implements UserIdentity.Scope public void initialize () throws Exception { - super.initialize(); - if (_extInstance || _initOnStartup) - { - try + if(!_initialized){ + super.initialize(); + if (_extInstance || _initOnStartup) { - initServlet(); - } - catch(Exception e) - { - if (_servletHandler.isStartWithUnavailable()) - LOG.ignore(e); - else - throw e; + try + { + initServlet(); + } + catch(Exception e) + { + if (_servletHandler.isStartWithUnavailable()) + LOG.ignore(e); + else + throw e; + } } } + _initialized = true; } @@ -443,6 +446,7 @@ public class ServletHolder extends Holder implements UserIdentity.Scope _servlet=null; _config=null; + _initialized = false; } /* ------------------------------------------------------------ */ diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherForwardTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherForwardTest.java index 825a4ae60bd..51e9f0d910d 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherForwardTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherForwardTest.java @@ -21,6 +21,8 @@ package org.eclipse.jetty.servlet; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; @@ -88,6 +90,7 @@ public class DispatcherForwardTest // 2. assert query => a=1 one // 1. assert query => a=1 one + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; servlet1 = new HttpServlet() { @@ -100,6 +103,7 @@ public class DispatcherForwardTest checkThat(req.getQueryString(),Matchers.equalTo(query1)); checkThat(req.getParameter("a"),Matchers.equalTo("1 one")); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -120,6 +124,7 @@ public class DispatcherForwardTest "Connection: close\r\n" + "\r\n"; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -131,7 +136,8 @@ public class DispatcherForwardTest // 2. assert query => a=2 // 1. assert query => a=1 - final String query1 = "a=1$20one&b=2%20two"; + CountDownLatch latch = new CountDownLatch(1); + final String query1 = "a=1%20one&b=2%20two"; final String query2 = "a=3%20three"; final String query3 = "a=3%20three&b=2%20two"; servlet1 = new HttpServlet() @@ -143,9 +149,10 @@ public class DispatcherForwardTest req.getRequestDispatcher("/two?" + query2).forward(req, resp); - checkThat(req.getQueryString(),Matchers.equalTo(query1)); + checkThat(req.getQueryString(), Matchers.equalTo(query1)); checkThat(req.getParameter("a"),Matchers.equalTo("1 one")); checkThat(req.getParameter("b"),Matchers.equalTo("2 two")); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -167,6 +174,7 @@ public class DispatcherForwardTest "Connection: close\r\n" + "\r\n"; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -178,6 +186,7 @@ public class DispatcherForwardTest // 2. assert query => a=1&b=2 // 1. assert query => a=1 + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String query2 = "b=2%20two"; final String query3 = "b=2%20two&a=1%20one"; @@ -192,6 +201,7 @@ public class DispatcherForwardTest checkThat(req.getQueryString(),Matchers.equalTo(query1)); checkThat(req.getParameter("a"),Matchers.equalTo("1 one")); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -213,6 +223,7 @@ public class DispatcherForwardTest "Connection: close\r\n" + "\r\n"; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -224,6 +235,7 @@ public class DispatcherForwardTest // 2. assert query => a=1 + params => a=1,2 // 1. assert query => a=1 + params => a=1,2 + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String form = "a=2%20two"; servlet1 = new HttpServlet() @@ -240,6 +252,7 @@ public class DispatcherForwardTest checkThat(values, Matchers.notNullValue()); checkThat(2, Matchers.equalTo(values.length)); checkThat(values, Matchers.arrayContainingInAnyOrder("1 one", "2 two")); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -266,6 +279,7 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -277,6 +291,7 @@ public class DispatcherForwardTest // 2. assert query => a=3 + params => a=3,2,1 // 1. assert query => a=1 + params => a=1,2 + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String query2 = "a=3%20three"; final String form = "a=2%20two"; @@ -294,6 +309,7 @@ public class DispatcherForwardTest checkThat(values, Matchers.notNullValue()); checkThat(2, Matchers.equalTo(values.length)); checkThat(values, Matchers.arrayContainingInAnyOrder("1 one", "2 two")); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -320,6 +336,7 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -331,6 +348,7 @@ public class DispatcherForwardTest // 2. assert query => a=1&c=3 + params => a=1&b=2&c=3 // 1. assert query => a=1 + params => a=1&b=2 + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String query2 = "c=3%20three"; final String query3 = "c=3%20three&a=1%20one"; @@ -348,6 +366,7 @@ public class DispatcherForwardTest checkThat(req.getParameter("a"),Matchers.equalTo("1 one")); checkThat(req.getParameter("b"),Matchers.equalTo("2 two")); checkThat(req.getParameter("c"), Matchers.nullValue()); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -373,6 +392,7 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @@ -385,6 +405,7 @@ public class DispatcherForwardTest // 2. assert query => a=1&c=3 + params => a=1&b=2&c=3 // 1. assert query => a=1 + params => a=1&b=2 + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String query2 = "c=3%20three"; final String query3 = "c=3%20three&a=1%20one"; @@ -404,6 +425,7 @@ public class DispatcherForwardTest checkThat(req.getParameter("a"),Matchers.equalTo("1 one")); checkThat(req.getParameter("b"),Matchers.equalTo("2 two")); checkThat(req.getParameter("c"), Matchers.nullValue()); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -429,12 +451,14 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @Test public void testContentCanBeReadViaInputStreamAfterForwardWithoutQuery() throws Exception { + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String form = "c=3%20three"; servlet1 = new HttpServlet() @@ -448,6 +472,7 @@ public class DispatcherForwardTest checkThat(req.getQueryString(),Matchers.equalTo(query1)); checkThat(req.getParameter("c"), Matchers.nullValue()); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -473,12 +498,14 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } @Test public void testContentCanBeReadViaInputStreamAfterForwardWithQuery() throws Exception { + CountDownLatch latch = new CountDownLatch(1); final String query1 = "a=1%20one"; final String query2 = "b=2%20two"; final String query3 = "b=2%20two&a=1%20one"; @@ -494,6 +521,7 @@ public class DispatcherForwardTest checkThat(req.getQueryString(),Matchers.equalTo(query1)); checkThat(req.getParameter("c"), Matchers.nullValue()); + latch.countDown(); } }; servlet2 = new HttpServlet() @@ -520,6 +548,7 @@ public class DispatcherForwardTest "\r\n" + form; String response = connector.getResponses(request); + Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(response, response.startsWith("HTTP/1.1 200")); } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DefaultServletStarvationTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DefaultServletStarvationTest.java deleted file mode 100644 index e0908085797..00000000000 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DefaultServletStarvationTest.java +++ /dev/null @@ -1,213 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.servlets; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.io.ManagedSelector; -import org.eclipse.jetty.io.SelectChannelEndPoint; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.toolchain.test.MavenTestingUtils; -import org.eclipse.jetty.toolchain.test.TestTracker; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.junit.After; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; - -public class DefaultServletStarvationTest -{ - @Rule - public TestTracker tracker = new TestTracker(); - private Server _server; - - @After - public void dispose() throws Exception - { - if (_server != null) - _server.stop(); - } - - @Test - public void testDefaultServletStarvation() throws Exception - { - int maxThreads = 2; - QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, maxThreads); - threadPool.setDetailedDump(true); - _server = new Server(threadPool); - - // Prepare a big file to download. - File directory = MavenTestingUtils.getTargetTestingDir(); - Files.createDirectories(directory.toPath()); - String resourceName = "resource.bin"; - Path resourcePath = Paths.get(directory.getPath(), resourceName); - try (OutputStream output = Files.newOutputStream(resourcePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) - { - byte[] chunk = new byte[1024]; - Arrays.fill(chunk,(byte)'X'); - chunk[chunk.length-2]='\r'; - chunk[chunk.length-1]='\n'; - for (int i = 0; i < 256 * 1024; ++i) - output.write(chunk); - } - - final CountDownLatch writePending = new CountDownLatch(1); - ServerConnector connector = new ServerConnector(_server, 0, 1) - { - @Override - protected SelectChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey key) throws IOException - { - return new SelectChannelEndPoint(channel, selectSet, key, getScheduler(), getIdleTimeout()) - { - @Override - protected void onIncompleteFlush() - { - super.onIncompleteFlush(); - writePending.countDown(); - } - }; - } - }; - _server.addConnector(connector); - - ServletContextHandler context = new ServletContextHandler(_server, "/"); - context.setResourceBase(directory.toURI().toString()); - context.addServlet(DefaultServlet.class, "/*").setAsyncSupported(false); - _server.setHandler(context); - - _server.start(); - - List sockets = new ArrayList<>(); - for (int i = 0; i < maxThreads; ++i) - { - Socket socket = new Socket("localhost", connector.getLocalPort()); - sockets.add(socket); - OutputStream output = socket.getOutputStream(); - String request = "" + - "GET /" + resourceName + " HTTP/1.1\r\n" + - "Host: localhost\r\n" + -// "Connection: close\r\n" + - "\r\n"; - output.write(request.getBytes(StandardCharsets.UTF_8)); - output.flush(); - Thread.sleep(100); - } - - - // Wait for a the servlet to block. - Assert.assertTrue(writePending.await(5, TimeUnit.SECONDS)); - - Thread.sleep(1000); - _server.dumpStdErr(); - Thread.sleep(1000); - - - ScheduledFuture dumper = Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() - { - @Override - public void run() - { - _server.dumpStdErr(); - } - }, 10, TimeUnit.SECONDS); - - - long expected = Files.size(resourcePath); - byte[] buffer = new byte[48 * 1024]; - for (Socket socket : sockets) - { - String socketString = socket.toString(); - long total = 0; - InputStream input = socket.getInputStream(); - - // look for CRLFCRLF - StringBuilder header = new StringBuilder(); - int state=0; - while (state<4 && header.length()<2048) - { - int ch=input.read(); - if (ch<0) - break; - header.append((char)ch); - switch(state) - { - case 0: - if (ch=='\r') - state=1; - break; - case 1: - if (ch=='\n') - state=2; - else - state=0; - break; - case 2: - if (ch=='\r') - state=3; - else - state=0; - break; - case 3: - if (ch=='\n') - state=4; - else - state=0; - break; - } - } - - while (total sockets = new ArrayList<>(); + for (int i = 0; i < maxThreads*2; ++i) + { + Socket socket = new Socket("localhost", connector.getLocalPort()); + sockets.add(socket); + OutputStream output = socket.getOutputStream(); + String request = "" + + "GET /" + resourceName + " HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "\r\n"; + output.write(request.getBytes(StandardCharsets.UTF_8)); + output.flush(); + Thread.sleep(100); + } + + // Wait for a the servlet to block. + Assert.assertTrue(writePending.await(5, TimeUnit.SECONDS)); + + long expected = Files.size(resourcePath); + byte[] buffer = new byte[48 * 1024]; + List> totals = new ArrayList<>(); + for (Socket socket : sockets) + { + final Exchanger x = new Exchanger<>(); + totals.add(x); + final InputStream input = socket.getInputStream(); + + new Thread() + { + @Override + public void run() + { + long total=0; + try + { + // look for CRLFCRLF + StringBuilder header = new StringBuilder(); + int state=0; + while (state<4 && header.length()<2048) + { + int ch=input.read(); + if (ch<0) + break; + header.append((char)ch); + switch(state) + { + case 0: + if (ch=='\r') + state=1; + break; + case 1: + if (ch=='\n') + state=2; + else + state=0; + break; + case 2: + if (ch=='\r') + state=3; + else + state=0; + break; + case 3: + if (ch=='\n') + state=4; + else + state=0; + break; + } + } + + while (total x : totals) + { + Long total = x.exchange(-1L,10000,TimeUnit.SECONDS); + Assert.assertEquals(expected,total.longValue()); + } + + // We could read everything, good. + for (Socket socket : sockets) + socket.close(); + } + + @Test + public void testFailureStarvation() throws Exception + { + try + { + ((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(true); + + int acceptors = 0; + int selectors = 1; + int maxThreads = 10; + final int barried=maxThreads-acceptors-selectors; + final CyclicBarrier barrier = new CyclicBarrier(barried); + + + QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, maxThreads); + threadPool.setDetailedDump(true); + _server = new Server(threadPool); + + + ServerConnector connector = new ServerConnector(_server, acceptors, selectors) + { + @Override + protected SelectChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey key) throws IOException + { + return new SelectChannelEndPoint(channel, selectSet, key, getScheduler(), getIdleTimeout()) + { + + @Override + public boolean flush(ByteBuffer... buffers) throws IOException + { + super.flush(buffers[0]); + throw new IOException("TEST FAILURE"); + } + + }; + } + }; + connector.setIdleTimeout(Long.MAX_VALUE); + _server.addConnector(connector); + + final AtomicInteger count = new AtomicInteger(0); + _server.setHandler(new AbstractHandler() + { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + int c=count.getAndIncrement(); + try + { + if (c sockets = new ArrayList<>(); + for (int i = 0; i < maxThreads*2; ++i) + { + Socket socket = new Socket("localhost", connector.getLocalPort()); + sockets.add(socket); + OutputStream output = socket.getOutputStream(); + String request = "" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + // "Connection: close\r\n" + + "\r\n"; + output.write(request.getBytes(StandardCharsets.UTF_8)); + output.flush(); + } + + + byte[] buffer = new byte[48 * 1024]; + List> totals = new ArrayList<>(); + for (Socket socket : sockets) + { + final Exchanger x = new Exchanger<>(); + totals.add(x); + final InputStream input = socket.getInputStream(); + + new Thread() + { + @Override + public void run() + { + int read=0; + try + { + // look for CRLFCRLF + StringBuilder header = new StringBuilder(); + int state=0; + while (state<4 && header.length()<2048) + { + int ch=input.read(); + if (ch<0) + break; + header.append((char)ch); + switch(state) + { + case 0: + if (ch=='\r') + state=1; + break; + case 1: + if (ch=='\n') + state=2; + else + state=0; + break; + case 2: + if (ch=='\r') + state=3; + else + state=0; + break; + case 3: + if (ch=='\n') + state=4; + else + state=0; + break; + } + } + + read=input.read(buffer); + } + catch (IOException e) + { + // e.printStackTrace(); + } + finally + { + try + { + x.exchange(read); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + } + }.start(); + } + + for (Exchanger x : totals) + { + Integer read = x.exchange(-1,10,TimeUnit.SECONDS); + Assert.assertEquals(-1,read.intValue()); + } + + // We could read everything, good. + for (Socket socket : sockets) + socket.close(); + + _server.stop(); + } + finally + { + ((StdErrLog)Log.getLogger(HttpChannel.class)).setHideStacks(false); + } + } +} diff --git a/tests/test-http-client-transport/pom.xml b/tests/test-http-client-transport/pom.xml index ec8e245353e..5913b35443e 100644 --- a/tests/test-http-client-transport/pom.xml +++ b/tests/test-http-client-transport/pom.xml @@ -17,6 +17,36 @@ + + maven-dependency-plugin + + + copy + generate-resources + + copy + + + + + org.mortbay.jetty.alpn + alpn-boot + ${alpn.version} + jar + false + ${project.build.directory}/alpn + + + + + + + + maven-surefire-plugin + + -Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar + + org.apache.maven.plugins maven-deploy-plugin @@ -47,6 +77,12 @@ ${project.version} test + + org.eclipse.jetty + jetty-alpn-server + ${project.version} + test + org.eclipse.jetty.http2 http2-http-client-transport diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java index 0cc5a0fb89b..ca377c311c2 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java @@ -18,22 +18,28 @@ package org.eclipse.jetty.http.client; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; +import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClientTransport; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; +import org.eclipse.jetty.http2.HTTP2Cipher; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; +import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.toolchain.test.TestTracker; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.After; import org.junit.Rule; @@ -44,15 +50,16 @@ import org.junit.runners.Parameterized; public abstract class AbstractTest { @Parameterized.Parameters(name = "transport: {0}") - public static List parameters() throws Exception + public static Object[] parameters() throws Exception { - return Arrays.asList(new Object[]{Transport.HTTP}, new Object[]{Transport.HTTP2}); + return new Object[]{Transport.HTTP, Transport.HTTPS, Transport.H2C, Transport.H2}; } @Rule public final TestTracker tracker = new TestTracker(); protected final Transport transport; + protected SslContextFactory sslContextFactory; protected Server server; protected ServerConnector connector; protected HttpClient client; @@ -64,11 +71,18 @@ public abstract class AbstractTest public void start(Handler handler) throws Exception { + sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); + sslContextFactory.setKeyStorePassword("storepwd"); + sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); + sslContextFactory.setTrustStorePassword("storepwd"); + sslContextFactory.setUseCipherSuitesOrder(true); + sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR); startServer(handler); startClient(); } - protected void startServer(Handler handler) throws Exception + private void startServer(Handler handler) throws Exception { QueuedThreadPool serverThreads = new QueuedThreadPool(); serverThreads.setName("server"); @@ -79,26 +93,58 @@ public abstract class AbstractTest server.start(); } - protected void startClient() throws Exception + private void startClient() throws Exception { QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(provideClientTransport(transport), null); + client = new HttpClient(provideClientTransport(transport), sslContextFactory); client.setExecutor(clientThreads); client.start(); } - private ConnectionFactory provideServerConnectionFactory(Transport transport) + private ConnectionFactory[] provideServerConnectionFactory(Transport transport) { + List result = new ArrayList<>(); switch (transport) { case HTTP: - return new HttpConnectionFactory(new HttpConfiguration()); - case HTTP2: - return new HTTP2ServerConnectionFactory(new HttpConfiguration()); + { + result.add(new HttpConnectionFactory(new HttpConfiguration())); + break; + } + case HTTPS: + { + HttpConfiguration configuration = new HttpConfiguration(); + configuration.addCustomizer(new SecureRequestCustomizer()); + HttpConnectionFactory http = new HttpConnectionFactory(configuration); + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, http.getProtocol()); + result.add(ssl); + result.add(http); + break; + } + case H2C: + { + result.add(new HTTP2CServerConnectionFactory(new HttpConfiguration())); + break; + } + case H2: + { + HttpConfiguration configuration = new HttpConfiguration(); + configuration.addCustomizer(new SecureRequestCustomizer()); + HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(configuration); + ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory("h2"); + SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol()); + result.add(ssl); + result.add(alpn); + result.add(h2); + break; + } default: + { throw new IllegalArgumentException(); + } } + return result.toArray(new ConnectionFactory[result.size()]); } private HttpClientTransport provideClientTransport(Transport transport) @@ -106,10 +152,12 @@ public abstract class AbstractTest switch (transport) { case HTTP: + case HTTPS: { return new HttpClientTransportOverHTTP(1); } - case HTTP2: + case H2C: + case H2: { HTTP2Client http2Client = new HTTP2Client(); http2Client.setSelectors(1); @@ -122,6 +170,21 @@ public abstract class AbstractTest } } + protected String newURI() + { + switch (transport) + { + case HTTP: + case H2C: + return "http://localhost:" + connector.getLocalPort(); + case HTTPS: + case H2: + return "https://localhost:" + connector.getLocalPort(); + default: + throw new IllegalArgumentException(); + } + } + @After public void stop() throws Exception { @@ -133,6 +196,6 @@ public abstract class AbstractTest protected enum Transport { - HTTP, HTTP2 + HTTP, HTTPS, H2C, H2 } } diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncRequestContentTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncRequestContentTest.java index 09ff0b0b043..052c90285b6 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncRequestContentTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncRequestContentTest.java @@ -53,7 +53,7 @@ public class AsyncRequestContentTest extends AbstractTest DeferredContentProvider contentProvider = new DeferredContentProvider(); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { @@ -73,7 +73,7 @@ public class AsyncRequestContentTest extends AbstractTest DeferredContentProvider contentProvider = new DeferredContentProvider(); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { @@ -95,7 +95,7 @@ public class AsyncRequestContentTest extends AbstractTest InputStreamContentProvider contentProvider = new InputStreamContentProvider(new ByteArrayInputStream(new byte[0])); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { @@ -116,7 +116,7 @@ public class AsyncRequestContentTest extends AbstractTest InputStreamContentProvider contentProvider = new InputStreamContentProvider(new ByteArrayInputStream(new byte[1])); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { @@ -136,7 +136,7 @@ public class AsyncRequestContentTest extends AbstractTest OutputStreamContentProvider contentProvider = new OutputStreamContentProvider(); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { @@ -156,7 +156,7 @@ public class AsyncRequestContentTest extends AbstractTest OutputStreamContentProvider contentProvider = new OutputStreamContentProvider(); CountDownLatch latch = new CountDownLatch(1); - client.POST("http://localhost:" + connector.getLocalPort()) + client.POST(newURI()) .content(contentProvider) .send(result -> { diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientIdleTimeoutTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientIdleTimeoutTest.java index ff4d24d4aa6..e168a0f3ef4 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientIdleTimeoutTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientIdleTimeoutTest.java @@ -27,8 +27,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.junit.Assert; @@ -61,14 +59,10 @@ public class HttpClientIdleTimeoutTest extends AbstractTest client.start(); final CountDownLatch latch = new CountDownLatch(1); - client.newRequest("localhost", connector.getLocalPort()).send(new Response.CompleteListener() + client.newRequest(newURI()).send(result -> { - @Override - public void onComplete(Result result) - { - if (result.isFailed()) - latch.countDown(); - } + if (result.isFailed()) + latch.countDown(); }); Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS)); @@ -89,16 +83,12 @@ public class HttpClientIdleTimeoutTest extends AbstractTest }); final CountDownLatch latch = new CountDownLatch(1); - client.newRequest("localhost", connector.getLocalPort()) + client.newRequest(newURI()) .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) - .send(new Response.CompleteListener() + .send(result -> { - @Override - public void onComplete(Result result) - { - if (result.isFailed()) - latch.countDown(); - } + if (result.isFailed()) + latch.countDown(); }); Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS)); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTest.java index 8bcb943abed..56ffdd156da 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientTest.java @@ -61,7 +61,7 @@ public class HttpClientTest extends AbstractTest } }); - ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) + ContentResponse response = client.newRequest(newURI()) .timeout(5, TimeUnit.SECONDS) .send(); @@ -95,7 +95,7 @@ public class HttpClientTest extends AbstractTest } }); - org.eclipse.jetty.client.api.Request request = client.newRequest("localhost", connector.getLocalPort()); + org.eclipse.jetty.client.api.Request request = client.newRequest(newURI()); FutureResponseListener listener = new FutureResponseListener(request, length); request.timeout(10, TimeUnit.SECONDS).send(listener); ContentResponse response = listener.get(); @@ -139,7 +139,7 @@ public class HttpClientTest extends AbstractTest } }); - org.eclipse.jetty.client.api.Request request = client.newRequest("localhost", connector.getLocalPort()); + org.eclipse.jetty.client.api.Request request = client.newRequest(newURI()); FutureResponseListener listener = new FutureResponseListener(request, 2 * length); request.timeout(10, TimeUnit.SECONDS).send(listener); ContentResponse response = listener.get(); @@ -183,7 +183,7 @@ public class HttpClientTest extends AbstractTest } }); - ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) + ContentResponse response = client.newRequest(newURI()) .method(HttpMethod.POST) .content(new BytesContentProvider(bytes)) .timeout(15, TimeUnit.SECONDS) @@ -228,7 +228,7 @@ public class HttpClientTest extends AbstractTest int chunkSize = 16; byte[][] bytes = IntStream.range(0, chunks).mapToObj(x -> new byte[chunkSize]).toArray(byte[][]::new); BytesContentProvider contentProvider = new BytesContentProvider("application/octet-stream", bytes); - ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) + ContentResponse response = client.newRequest(newURI()) .method(HttpMethod.POST) .content(contentProvider) .timeout(15, TimeUnit.SECONDS) diff --git a/tests/test-http-client-transport/src/test/resources/keystore.jks b/tests/test-http-client-transport/src/test/resources/keystore.jks new file mode 100644 index 00000000000..428ba54776e Binary files /dev/null and b/tests/test-http-client-transport/src/test/resources/keystore.jks differ diff --git a/tests/test-http-client-transport/src/test/resources/truststore.jks b/tests/test-http-client-transport/src/test/resources/truststore.jks new file mode 100644 index 00000000000..839cb8c3515 Binary files /dev/null and b/tests/test-http-client-transport/src/test/resources/truststore.jks differ