diff --git a/Jenkinsfile b/Jenkinsfile index 79402a71340..8e2db60c6ae 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -97,7 +97,7 @@ def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) { mavenOpts: mavenOpts, mavenLocalRepo: localRepo) { // Some common Maven command line + provided command line - sh "mvn -V -B -T3 -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME + sh "mvn -Pci -V -B -T3 -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME } } diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java index 169ae96ec0a..5f23ad4fda2 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/FastFileServer.java @@ -25,7 +25,6 @@ import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.file.StandardOpenOption; - import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -116,7 +115,8 @@ public class FastFileServer } String listing = Resource.newResource(file).getListHTML( request.getRequestURI(), - request.getPathInfo().lastIndexOf("/") > 0); + request.getPathInfo().lastIndexOf("/") > 0, + request.getQueryString()); response.setContentType("text/html; charset=utf-8"); response.getWriter().println(listing); return; diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java index 12ddbf4f6b0..a72c660879a 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/Http2Server.java @@ -60,10 +60,6 @@ import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlets.PushCacheFilter; import org.eclipse.jetty.util.ssl.SslContextFactory; - -/* ------------------------------------------------------------ */ -/** - */ public class Http2Server { public static void main(String... args) throws Exception @@ -102,7 +98,7 @@ public class Http2Server String jetty_distro = System.getProperty("jetty.distro","../../jetty-distribution/target/distribution"); if (!new File(jetty_distro).exists()) jetty_distro = "jetty-distribution/target/distribution"; - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(jetty_distro + "/demo-base/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 1ad19b730cd..1cd09c4cb36 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -139,7 +139,7 @@ public class LikeJettyXml // === jetty-https.xml === // SSL Context Factory - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java index 851d584c63c..960563ab340 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ManyConnectors.java @@ -20,9 +20,7 @@ package org.eclipse.jetty.embedded; import java.io.File; import java.io.FileNotFoundException; -import java.security.Security; -import org.conscrypt.OpenSSLProvider; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; @@ -89,7 +87,7 @@ public class ManyConnectors // including things like choosing the particular certificate out of a // keystore to be used. - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath()); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); diff --git a/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2ServerTest.java b/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2ServerTest.java index d5ddef65ed6..f17c3283fd8 100644 --- a/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2ServerTest.java +++ b/jetty-alpn/jetty-alpn-conscrypt-server/src/test/java/org/eclipse/jetty/alpn/conscrypt/server/ConscryptHTTP2ServerTest.java @@ -32,6 +32,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Request; @@ -60,24 +61,35 @@ public class ConscryptHTTP2ServerTest private Server server = new Server(); - private SslContextFactory newSslContextFactory() + private SslContextFactory.Server newServerSslContextFactory() + { + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); + configureSslContextFactory(sslContextFactory); + return sslContextFactory; + } + + private SslContextFactory.Client newClientSslContextFactory() + { + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + configureSslContextFactory(sslContextFactory); + sslContextFactory.setEndpointIdentificationAlgorithm(null); + return sslContextFactory; + } + + private void configureSslContextFactory(SslContextFactory sslContextFactory) { Path path = Paths.get("src", "test", "resources"); File keys = path.resolve("keystore").toFile(); - - SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStorePath(keys.getAbsolutePath()); sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setTrustStorePath(keys.getAbsolutePath()); - sslContextFactory.setKeyStorePath(keys.getAbsolutePath()); sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setProvider("Conscrypt"); - sslContextFactory.setEndpointIdentificationAlgorithm(null); if (JavaVersion.VERSION.getPlatform() < 9) { // Conscrypt enables TLSv1.3 by default but it's not supported in Java 8. sslContextFactory.addExcludeProtocols("TLSv1.3"); } - return sslContextFactory; } @BeforeEach @@ -94,7 +106,7 @@ public class ConscryptHTTP2ServerTest HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig); ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); alpn.setDefaultProtocol(http.getProtocol()); - SslConnectionFactory ssl = new SslConnectionFactory(newSslContextFactory(), alpn.getProtocol()); + SslConnectionFactory ssl = new SslConnectionFactory(newServerSslContextFactory(), alpn.getProtocol()); ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, h2, http); http2Connector.setPort(0); @@ -123,8 +135,10 @@ public class ConscryptHTTP2ServerTest @Test public void testSimpleRequest() throws Exception { - HTTP2Client h2Client = new HTTP2Client(); - HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client), newSslContextFactory()); + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSslContextFactory(newClientSslContextFactory()); + HTTP2Client h2Client = new HTTP2Client(clientConnector); + HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client)); client.start(); try { diff --git a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java index 7e818bbc520..5fcc2feca09 100644 --- a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java +++ b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java @@ -59,7 +59,7 @@ public class JDK9ALPNTest HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpConfiguration); ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); alpn.setDefaultProtocol(h1.getProtocol()); - connector = new ServerConnector(server, newSslContextFactory(), alpn, h1, h2); + connector = new ServerConnector(server, newServerSslContextFactory(), alpn, h1, h2); server.addConnector(connector); server.setHandler(handler); server.start(); @@ -72,9 +72,9 @@ public class JDK9ALPNTest server.stop(); } - private SslContextFactory newSslContextFactory() + private SslContextFactory.Server newServerSslContextFactory() { - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); @@ -95,7 +95,7 @@ public class JDK9ALPNTest } }); - SslContextFactory sslContextFactory = new SslContextFactory(true); + SslContextFactory sslContextFactory = new SslContextFactory.Client(true); sslContextFactory.start(); SSLContext sslContext = sslContextFactory.getSslContext(); try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort())) @@ -137,7 +137,7 @@ public class JDK9ALPNTest } }); - SslContextFactory sslContextFactory = new SslContextFactory(true); + SslContextFactory sslContextFactory = new SslContextFactory.Client(true); sslContextFactory.start(); SSLContext sslContext = sslContextFactory.getSslContext(); try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort())) diff --git a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9HTTP2Server.java b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9HTTP2Server.java index d2d2ce12536..763488f5750 100644 --- a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9HTTP2Server.java +++ b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9HTTP2Server.java @@ -45,7 +45,7 @@ public class JDK9HTTP2Server httpsConfig.setSendServerVersion(true); httpsConfig.addCustomizer(new SecureRequestCustomizer()); - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java index 1388931e233..a51aea42b9b 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -217,6 +218,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler path = request.getPath(); } Request newRequest = client.copyRequest(request, requestURI); + // Disable the timeout so that only the one from the initial request applies. + newRequest.timeout(0, TimeUnit.MILLISECONDS); if (path != null) newRequest.path(path); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java index feff1232642..4b82e97e490 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java @@ -159,47 +159,11 @@ public class HttpClient extends ContainerLifeCycle this(new HttpClientTransportOverHTTP()); } - /** - * Creates a HttpClient instance that can perform HTTP requests to non-TLS and TLS destinations - * (that is, both requests with the "http" scheme and with the "https" scheme). - * - * @param sslContextFactory the {@link SslContextFactory} that manages TLS encryption - * @see #getSslContextFactory() - * @deprecated configure the SslContextFactory on the transport's {@link ClientConnector} - */ - @Deprecated - public HttpClient(SslContextFactory sslContextFactory) - { - this(new HttpClientTransportOverHTTP(), sslContextFactory); - } - public HttpClient(HttpClientTransport transport) - { - this(null, transport); - } - - /** - * Creates a HttpClient instance that can perform HTTP requests with the given transport - * to non-TLS and TLS destinations (that is, both requests with the "http" scheme and with - * the "https" scheme). - * - * @param transport the transport that sends and receives HTTP requests and responses - * @param sslContextFactory the {@link SslContextFactory} that manages TLS encryption - * @deprecated configure the SslContextFactory on the transport's {@link ClientConnector} - */ - @Deprecated - public HttpClient(HttpClientTransport transport, SslContextFactory sslContextFactory) - { - this(sslContextFactory, transport); - } - - private HttpClient(SslContextFactory sslContextFactory, HttpClientTransport transport) { this.transport = Objects.requireNonNull(transport); addBean(transport); this.connector = ((AbstractHttpClientTransport)transport).getBean(ClientConnector.class); - if (sslContextFactory != null) - connector.setSslContextFactory(sslContextFactory); addBean(handlers); addBean(decoderFactories); } @@ -217,9 +181,8 @@ public class HttpClient extends ContainerLifeCycle /** * @return the {@link SslContextFactory} that manages TLS encryption - * @see #HttpClient(SslContextFactory) */ - public SslContextFactory getSslContextFactory() + public SslContextFactory.Client getSslContextFactory() { return connector.getSslContextFactory(); } @@ -955,7 +918,7 @@ public class HttpClient extends ContainerLifeCycle } /** - * @return the max number of HTTP redirects that are followed + * @return the max number of HTTP redirects that are followed in a conversation * @see #setMaxRedirects(int) */ public int getMaxRedirects() @@ -964,7 +927,7 @@ public class HttpClient extends ContainerLifeCycle } /** - * @param maxRedirects the max number of HTTP redirects that are followed + * @param maxRedirects the max number of HTTP redirects that are followed in a conversation, or -1 for unlimited redirects * @see #setFollowRedirects(boolean) */ public void setMaxRedirects(int maxRedirects) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConversation.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConversation.java index a555d700965..3f57de2b9fc 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConversation.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConversation.java @@ -25,9 +25,13 @@ import java.util.concurrent.ConcurrentLinkedDeque; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; public class HttpConversation extends AttributesMap { + private static final Logger LOG = Log.getLogger(HttpConversation.class); + private final Deque exchanges = new ConcurrentLinkedDeque<>(); private volatile List listeners; @@ -118,6 +122,7 @@ public class HttpConversation extends AttributesMap HttpExchange lastExchange = exchanges.peekLast(); if (firstExchange == lastExchange) { + // We don't have a conversation, just a single request. if (overrideListener != null) listeners.add(overrideListener); else @@ -125,13 +130,16 @@ public class HttpConversation extends AttributesMap } else { - // Order is important, we want to notify the last exchange first + // We have a conversation (e.g. redirect, authentication). + // Order is important, we want to notify the last exchange first. listeners.addAll(lastExchange.getResponseListeners()); if (overrideListener != null) listeners.add(overrideListener); else listeners.addAll(firstExchange.getResponseListeners()); } + if (LOG.isDebugEnabled()) + LOG.debug("Exchanges in conversation {}, override={}, listeners={}", exchanges.size(), overrideListener, listeners); this.listeners = listeners; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java index 623f1d28732..14022463f73 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java @@ -72,12 +72,6 @@ public class HttpDestination extends ContainerLifeCycle implements Destination, private final TimeoutTask timeout; private ConnectionPool connectionPool; - @Deprecated - public HttpDestination(HttpClient client, Origin origin) - { - this(client, new Key(origin, null)); - } - public HttpDestination(HttpClient client, Key key) { this(client, key, Function.identity()); @@ -683,7 +677,11 @@ public class HttpDestination extends ContainerLifeCycle implements Destination, } } - // The TimeoutTask that expires when the next check of expiry is needed + /** + * This class enforces the total timeout for exchanges that are still in the queue. + * The total timeout for exchanges that are not in the destination queue is enforced + * by {@link HttpChannel}. + */ private class TimeoutTask extends CyclicTimeout { private final AtomicLong nextTimeout = new AtomicLong(Long.MAX_VALUE); @@ -696,6 +694,9 @@ public class HttpDestination extends ContainerLifeCycle implements Destination, @Override public void onTimeoutExpired() { + if (LOG.isDebugEnabled()) + LOG.debug("{} timeout expired", this); + nextTimeout.set(Long.MAX_VALUE); long now = System.nanoTime(); long nextExpiresAt = Long.MAX_VALUE; @@ -728,12 +729,16 @@ public class HttpDestination extends ContainerLifeCycle implements Destination, if (timeoutAt != expiresAt) { long delay = expiresAt - System.nanoTime(); - if (LOG.isDebugEnabled()) - LOG.debug("Scheduled timeout in {} ms", TimeUnit.NANOSECONDS.toMillis(delay)); if (delay <= 0) + { onTimeoutExpired(); + } else + { schedule(delay, TimeUnit.NANOSECONDS); + if (LOG.isDebugEnabled()) + LOG.debug("{} scheduled timeout in {} ms", this, TimeUnit.NANOSECONDS.toMillis(delay)); + } } } } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRedirector.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRedirector.java index 24bdc74d8c6..47292818600 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRedirector.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRedirector.java @@ -23,6 +23,7 @@ import java.net.URISyntaxException; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -61,10 +62,10 @@ public class HttpRedirector { private static final Logger LOG = Log.getLogger(HttpRedirector.class); private static final String SCHEME_REGEXP = "(^https?)"; - private static final String AUTHORITY_REGEXP = "([^/\\?#]+)"; + private static final String AUTHORITY_REGEXP = "([^/?#]+)"; // The location may be relative so the scheme://authority part may be missing private static final String DESTINATION_REGEXP = "(" + SCHEME_REGEXP + "://" + AUTHORITY_REGEXP + ")?"; - private static final String PATH_REGEXP = "([^\\?#]*)"; + private static final String PATH_REGEXP = "([^?#]*)"; private static final String QUERY_REGEXP = "([^#]*)"; private static final String FRAGMENT_REGEXP = "(.*)"; private static final Pattern URI_PATTERN = Pattern.compile(DESTINATION_REGEXP + PATH_REGEXP + QUERY_REGEXP + FRAGMENT_REGEXP); @@ -101,11 +102,11 @@ public class HttpRedirector /** * Redirects the given {@code response}, blocking until the redirect is complete. * - * @param request the original request that triggered the redirect + * @param request the original request that triggered the redirect * @param response the response to the original request * @return a {@link Result} object containing the request to the redirected location and its response * @throws InterruptedException if the thread is interrupted while waiting for the redirect to complete - * @throws ExecutionException if the redirect failed + * @throws ExecutionException if the redirect failed * @see #redirect(Request, Response, Response.CompleteListener) */ public Result redirect(Request request, Response response) throws InterruptedException, ExecutionException @@ -144,7 +145,7 @@ public class HttpRedirector /** * Redirects the given {@code response} asynchronously. * - * @param request the original request that triggered the redirect + * @param request the original request that triggered the redirect * @param response the response to the original request * @param listener the listener that receives response events * @return the request to the redirected location @@ -292,7 +293,8 @@ public class HttpRedirector Integer redirects = (Integer)conversation.getAttribute(ATTRIBUTE); if (redirects == null) redirects = 0; - if (redirects < client.getMaxRedirects()) + int maxRedirects = client.getMaxRedirects(); + if (maxRedirects < 0 || redirects < maxRedirects) { ++redirects; conversation.setAttribute(ATTRIBUTE, redirects); @@ -310,19 +312,17 @@ public class HttpRedirector try { Request redirect = client.copyRequest(httpRequest, location); + // Disable the timeout so that only the one from the initial request applies. + redirect.timeout(0, TimeUnit.MILLISECONDS); // Use given method redirect.method(method); - redirect.onRequestBegin(new Request.BeginListener() + redirect.onRequestBegin(request -> { - @Override - public void onBegin(Request redirect) - { - Throwable cause = httpRequest.getAbortCause(); - if (cause != null) - redirect.abort(cause); - } + Throwable cause = httpRequest.getAbortCause(); + if (cause != null) + request.abort(cause); }); redirect.send(listener); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/TimeoutCompleteListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/TimeoutCompleteListener.java index ced60b57239..7a3121a755b 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/TimeoutCompleteListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/TimeoutCompleteListener.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.io.CyclicTimeout; -import org.eclipse.jetty.util.component.Destroyable; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.Scheduler; @@ -47,7 +46,7 @@ public class TimeoutCompleteListener extends CyclicTimeout implements Response.C { Request request = this.request.getAndSet(null); if (LOG.isDebugEnabled()) - LOG.debug("Total timeout {} ms elapsed for {}", request.getTimeout(), request); + LOG.debug("Total timeout {} ms elapsed for {} on {}", request.getTimeout(), request, this); if (request != null) request.abort(new TimeoutException("Total timeout " + request.getTimeout() + " ms elapsed")); } @@ -60,7 +59,7 @@ public class TimeoutCompleteListener extends CyclicTimeout implements Response.C { boolean cancelled = cancel(); if (LOG.isDebugEnabled()) - LOG.debug("Cancelled ({}) timeout for {}", cancelled, request); + LOG.debug("Cancelled ({}) timeout for {} on {}", cancelled, request, this); } } @@ -69,12 +68,16 @@ public class TimeoutCompleteListener extends CyclicTimeout implements Response.C if (this.request.compareAndSet(null, request)) { long delay = timeoutAt - System.nanoTime(); - if (LOG.isDebugEnabled()) - LOG.debug("Scheduled timeout in {} ms for {}", TimeUnit.NANOSECONDS.toMillis(delay), request); if (delay <= 0) + { onTimeoutExpired(); + } else + { schedule(delay, TimeUnit.NANOSECONDS); + if (LOG.isDebugEnabled()) + LOG.debug("Scheduled timeout in {} ms for {} on {}", TimeUnit.NANOSECONDS.toMillis(delay), request, this); + } } } } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java index 97bcf4c9014..09f35d9ec12 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java @@ -261,12 +261,14 @@ public interface Request Request idleTimeout(long timeout, TimeUnit unit); /** - * @return the total timeout for this request, in milliseconds + * @return the total timeout for this request, in milliseconds; + * zero or negative if the timeout is disabled */ long getTimeout(); /** - * @param timeout the total timeout for the request/response conversation + * @param timeout the total timeout for the request/response conversation; + * use zero or a negative value to disable the timeout * @param unit the timeout unit * @return this request object */ diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java index dc47b51eebd..d5c7218362f 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpClientServerTest.java @@ -24,6 +24,7 @@ import java.util.stream.Stream; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -58,7 +59,7 @@ public abstract class AbstractHttpClientServerTest serverThreads.setName("server"); server = new Server(serverThreads); } - connector = new ServerConnector(server, scenario.newSslContextFactory()); + connector = new ServerConnector(server, scenario.newServerSslContextFactory()); connector.setPort(0); server.addConnector(connector); server.setHandler(handler); @@ -67,30 +68,30 @@ public abstract class AbstractHttpClientServerTest protected void startClient(final Scenario scenario) throws Exception { - startClient(scenario, null,null); + startClient(scenario, null); } - protected void startClient(final Scenario scenario, HttpClientTransport transport, Consumer config) throws Exception + protected void startClient(final Scenario scenario, Consumer config) throws Exception { - if (transport==null) - transport = new HttpClientTransportOverHTTP(1); - + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); + clientConnector.setSslContextFactory(scenario.newClientSslContextFactory()); + HttpClientTransport transport = new HttpClientTransportOverHTTP(clientConnector); QueuedThreadPool executor = new QueuedThreadPool(); executor.setName("client"); + clientConnector.setExecutor(executor); Scheduler scheduler = new ScheduledExecutorScheduler("client-scheduler", false); - client = newHttpClient(scenario, transport); - client.setExecutor(executor); - client.setScheduler(scheduler); + clientConnector.setScheduler(scheduler); + client = newHttpClient(transport); client.setSocketAddressResolver(new SocketAddressResolver.Sync()); - if (config!=null) + if (config != null) config.accept(client); - client.start(); } - public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport) + public HttpClient newHttpClient(HttpClientTransport transport) { - return new HttpClient(transport, scenario.newSslContextFactory()); + return new HttpClient(transport); } @AfterEach @@ -113,9 +114,10 @@ public abstract class AbstractHttpClientServerTest } } - public static class ScenarioProvider implements ArgumentsProvider { + public static class ScenarioProvider implements ArgumentsProvider + { @Override - public Stream provideArguments(ExtensionContext context) throws Exception + public Stream provideArguments(ExtensionContext context) { return Stream.of( new NormalScenario(), @@ -125,9 +127,10 @@ public abstract class AbstractHttpClientServerTest } } - public static class NonSslScenarioProvider implements ArgumentsProvider { + public static class NonSslScenarioProvider implements ArgumentsProvider + { @Override - public Stream provideArguments(ExtensionContext context) throws Exception + public Stream provideArguments(ExtensionContext context) { return Stream.of( new NormalScenario() @@ -138,12 +141,27 @@ public abstract class AbstractHttpClientServerTest public interface Scenario { - default SslContextFactory newSslContextFactory() { return null; } + SslContextFactory.Client newClientSslContextFactory(); + + SslContextFactory.Server newServerSslContextFactory(); + String getScheme(); } public static class NormalScenario implements Scenario { + @Override + public SslContextFactory.Client newClientSslContextFactory() + { + return null; + } + + @Override + public SslContextFactory.Server newServerSslContextFactory() + { + return null; + } + @Override public String getScheme() { @@ -160,15 +178,27 @@ public abstract class AbstractHttpClientServerTest public static class SslScenario implements Scenario { @Override - public SslContextFactory newSslContextFactory() + public SslContextFactory.Client newClientSslContextFactory() + { + SslContextFactory.Client result = new SslContextFactory.Client(); + result.setEndpointIdentificationAlgorithm(null); + configure(result); + return result; + } + + @Override + public SslContextFactory.Server newServerSslContextFactory() + { + SslContextFactory.Server result = new SslContextFactory.Server(); + configure(result); + return result; + } + + private void configure(SslContextFactory ssl) { Path keystorePath = MavenTestingUtils.getTestResourcePath("keystore.jks"); - - SslContextFactory ssl = new SslContextFactory(); - ssl.setEndpointIdentificationAlgorithm(""); ssl.setKeyStorePath(keystorePath.toString()); ssl.setKeyStorePassword("storepwd"); - return ssl; } @Override diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java index 6dd31ce1bf7..7dece557831 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ConnectionPoolTest.java @@ -18,9 +18,6 @@ package org.eclipse.jetty.client; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -31,7 +28,6 @@ import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; import java.util.stream.Stream; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -53,6 +49,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + @Disabled // Disabled by @gregw on issue #2540 - commit 621b946b10884e7308eacca241dcf8b5d6f6cff2 public class ConnectionPoolTest { @@ -83,7 +82,7 @@ public class ConnectionPoolTest transport.setConnectionPoolFactory(factory); server.start(); - client = new HttpClient(transport, null); + client = new HttpClient(transport); client.start(); } @@ -115,7 +114,7 @@ public class ConnectionPoolTest start(factory, new EmptyServerHandler() { @Override - protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { switch (HttpMethod.fromString(request.getMethod())) { diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java index 50238673069..878f683dd5d 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalSiteTest.java @@ -18,10 +18,6 @@ package org.eclipse.jetty.client; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - import java.net.Socket; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -30,12 +26,15 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.http.HttpScheme; -import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + @Disabled public class ExternalSiteTest { @@ -44,7 +43,7 @@ public class ExternalSiteTest @BeforeEach public void prepare() throws Exception { - client = new HttpClient(new SslContextFactory()); + client = new HttpClient(); client.start(); } @@ -64,28 +63,20 @@ public class ExternalSiteTest assumeCanConnectTo(host, port); final CountDownLatch latch1 = new CountDownLatch(1); - client.newRequest(host, port).send(new Response.CompleteListener() + client.newRequest(host, port).send(result -> { - @Override - public void onComplete(Result result) - { - if (!result.isFailed() && result.getResponse().getStatus() == 200) - latch1.countDown(); - } + if (!result.isFailed() && result.getResponse().getStatus() == 200) + latch1.countDown(); }); assertTrue(latch1.await(10, TimeUnit.SECONDS)); // Try again the same URI, but without specifying the port final CountDownLatch latch2 = new CountDownLatch(1); - client.newRequest("http://" + host).send(new Response.CompleteListener() + client.newRequest("http://" + host).send(result -> { - @Override - public void onComplete(Result result) - { - assertTrue(result.isSucceeded()); - assertEquals(200, result.getResponse().getStatus()); - latch2.countDown(); - } + assertTrue(result.isSucceeded()); + assertEquals(200, result.getResponse().getStatus()); + latch2.countDown(); }); assertTrue(latch2.await(10, TimeUnit.SECONDS)); } @@ -94,7 +85,7 @@ public class ExternalSiteTest public void testExternalSSLSite() throws Exception { client.stop(); - client = new HttpClient(new SslContextFactory()); + client = new HttpClient(); client.start(); String host = "api-3t.paypal.com"; @@ -104,14 +95,10 @@ public class ExternalSiteTest assumeCanConnectTo(host, port); final CountDownLatch latch = new CountDownLatch(1); - client.newRequest(host, port).scheme("https").path("/nvp").send(new Response.CompleteListener() + client.newRequest(host, port).scheme("https").path("/nvp").send(result -> { - @Override - public void onComplete(Result result) - { - if (result.isSucceeded() && result.getResponse().getStatus() == 200) - latch.countDown(); - } + if (result.isSucceeded() && result.getResponse().getStatus() == 200) + latch.countDown(); }); assertTrue(latch.await(5, TimeUnit.SECONDS)); } @@ -129,14 +116,7 @@ public class ExternalSiteTest { final CountDownLatch latch = new CountDownLatch(3); client.newRequest(host, port) - .onResponseFailure(new Response.FailureListener() - { - @Override - public void onFailure(Response response, Throwable failure) - { - latch.countDown(); - } - }) + .onResponseFailure((response, failure) -> latch.countDown()) .send(new Response.Listener.Adapter() { @Override @@ -180,7 +160,7 @@ public class ExternalSiteTest } catch (Throwable x) { - assumeTrue(x == null, "Unable to connect"); + assumeTrue(false, "Unable to connect"); } } } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java index 706471023fd..c8e1d5feb3a 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java @@ -18,19 +18,16 @@ package org.eclipse.jetty.client; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; - import java.io.IOException; import java.security.cert.CertificateException; import java.util.concurrent.ExecutionException; import javax.net.ssl.SSLHandshakeException; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.NetworkConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; @@ -40,11 +37,14 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterEach; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; + /** * This test class runs tests to make sure that hostname verification (http://www.ietf.org/rfc/rfc2818.txt * section 3.1) is configurable in SslContextFactory and works as expected. @@ -52,7 +52,7 @@ import org.junit.jupiter.api.Test; @Disabled public class HostnameVerificationTest { - private SslContextFactory clientSslContextFactory = new SslContextFactory(); + private SslContextFactory.Client clientSslContextFactory = new SslContextFactory.Client(); private Server server; private HttpClient client; private NetworkConnector connector; @@ -64,7 +64,7 @@ public class HostnameVerificationTest serverThreads.setName("server"); server = new Server(serverThreads); - SslContextFactory serverSslContextFactory = new SslContextFactory(); + SslContextFactory.Server serverSslContextFactory = new SslContextFactory.Server(); serverSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); serverSslContextFactory.setKeyStorePassword("storepwd"); connector = new ServerConnector(server, serverSslContextFactory); @@ -72,7 +72,7 @@ public class HostnameVerificationTest server.setHandler(new DefaultHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.getWriter().write("foobar"); @@ -80,14 +80,19 @@ public class HostnameVerificationTest }); server.start(); - // keystore contains a hostname which doesn't match localhost + // The keystore contains a hostname which doesn't match localhost clientSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); clientSslContextFactory.setKeyStorePassword("storepwd"); + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); + clientConnector.setSslContextFactory(clientSslContextFactory); + QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(clientSslContextFactory); - client.setExecutor(clientThreads); + clientConnector.setExecutor(clientThreads); + + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); client.start(); } @@ -112,9 +117,7 @@ public class HostnameVerificationTest clientSslContextFactory.setEndpointIdentificationAlgorithm("HTTPS"); String uri = "https://localhost:" + connector.getLocalPort() + "/"; - ExecutionException x = assertThrows(ExecutionException.class, ()->{ - client.GET(uri); - }); + ExecutionException x = assertThrows(ExecutionException.class, ()-> client.GET(uri)); Throwable cause = x.getCause(); assertThat(cause, Matchers.instanceOf(SSLHandshakeException.class)); Throwable root = cause.getCause().getCause(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java index 5e3307746a2..672b6272501 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java @@ -44,9 +44,11 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response.Listener; import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.AbstractAuthentication; import org.eclipse.jetty.client.util.BasicAuthentication; import org.eclipse.jetty.client.util.DeferredContentProvider; import org.eclipse.jetty.client.util.DigestAuthentication; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.ConstraintMapping; @@ -57,7 +59,6 @@ import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.security.authentication.DigestAuthenticator; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.IO; @@ -67,6 +68,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ArgumentsSource; +import static org.eclipse.jetty.client.api.Authentication.ANY_REALM; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalToIgnoringCase; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -137,7 +139,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest { startBasic(scenario, new EmptyServerHandler()); URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort()); - test_Authentication(scenario, new BasicAuthentication(uri, Authentication.ANY_REALM, "basic", "basic")); + test_Authentication(scenario, new BasicAuthentication(uri, ANY_REALM, "basic", "basic")); } @ParameterizedTest @@ -155,7 +157,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest { startDigest(scenario, new EmptyServerHandler()); URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort()); - test_Authentication(scenario, new DigestAuthentication(uri, Authentication.ANY_REALM, "digest", "digest")); + test_Authentication(scenario, new DigestAuthentication(uri, ANY_REALM, "digest", "digest")); } private void test_Authentication(final Scenario scenario, Authentication authentication) throws Exception @@ -227,16 +229,19 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest @ArgumentsSource(ScenarioProvider.class) public void test_BasicAuthentication_ThenRedirect(Scenario scenario) throws Exception { - startBasic(scenario, new AbstractHandler() + startBasic(scenario, new EmptyServerHandler() { private final AtomicInteger requests = new AtomicInteger(); @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - baseRequest.setHandled(true); - if (requests.incrementAndGet() == 1) - response.sendRedirect(URIUtil.newURI(scenario.getScheme(), request.getServerName(), request.getServerPort(), request.getRequestURI(), null)); + int r = requests.incrementAndGet(); + if (r == 1) + { + String path = request.getRequestURI() + "/" + r; + response.sendRedirect(URIUtil.newURI(scenario.getScheme(), request.getServerName(), request.getServerPort(), path, null)); + } } }); @@ -269,12 +274,11 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest @ArgumentsSource(ScenarioProvider.class) public void test_Redirect_ThenBasicAuthentication(Scenario scenario) throws Exception { - startBasic(scenario, new AbstractHandler() + startBasic(scenario, new EmptyServerHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - baseRequest.setHandled(true); if (request.getRequestURI().endsWith("/redirect")) response.sendRedirect(URIUtil.newURI(scenario.getScheme(), request.getServerName(), request.getServerPort(), "/secure", null)); } @@ -571,61 +575,57 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest assertTrue(resultLatch.await(5, TimeUnit.SECONDS)); } - private static class GeneratingContentProvider implements ContentProvider + @ParameterizedTest + @ArgumentsSource(ScenarioProvider.class) + public void test_InfiniteAuthentication(Scenario scenario) throws Exception { - private static final ByteBuffer DONE = ByteBuffer.allocate(0); - - private final IntFunction generator; - - private GeneratingContentProvider(IntFunction generator) + String authType = "Authenticate"; + start(scenario, new EmptyServerHandler() { - this.generator = generator; - } - - @Override - public long getLength() - { - return -1; - } - - @Override - public boolean isReproducible() - { - return true; - } - - @Override - public Iterator iterator() - { - return new Iterator() + @Override + protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - private int index; - public ByteBuffer current; + // Always reply with a 401 to see if the client + // can handle an infinite authentication loop. + response.setStatus(HttpStatus.UNAUTHORIZED_401); + response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), authType); + } + }); - @Override - @SuppressWarnings("ReferenceEquality") - public boolean hasNext() + AuthenticationStore authenticationStore = client.getAuthenticationStore(); + URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort()); + authenticationStore.addAuthentication(new AbstractAuthentication(uri, Authentication.ANY_REALM) + { + @Override + public String getType() + { + return authType; + } + + @Override + public Result authenticate(Request request, ContentResponse response, HeaderInfo headerInfo, Attributes context) + { + return new Result() { - if (current == null) + @Override + public URI getURI() { - current = generator.apply(index++); - if (current == null) - current = DONE; + return uri; } - return current != DONE; - } - @Override - public ByteBuffer next() - { - ByteBuffer result = current; - current = null; - if (result == null) - throw new NoSuchElementException(); - return result; - } - }; - } + @Override + public void apply(Request request) + { + } + }; + } + }); + + ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) + .scheme(scenario.getScheme()) + .send(); + + assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus()); } @Test @@ -801,4 +801,61 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest assertEquals("thermostat", headerInfo.getParameter("realm")); assertEquals(headerInfo.getParameter("nonce"), "1523430383="); } + + private static class GeneratingContentProvider implements ContentProvider + { + private static final ByteBuffer DONE = ByteBuffer.allocate(0); + + private final IntFunction generator; + + private GeneratingContentProvider(IntFunction generator) + { + this.generator = generator; + } + + @Override + public long getLength() + { + return -1; + } + + @Override + public boolean isReproducible() + { + return true; + } + + @Override + public Iterator iterator() + { + return new Iterator() + { + private int index; + public ByteBuffer current; + + @Override + @SuppressWarnings("ReferenceEquality") + public boolean hasNext() + { + if (current == null) + { + current = generator.apply(index++); + if (current == null) + current = DONE; + } + return current != DONE; + } + + @Override + public ByteBuffer next() + { + ByteBuffer result = current; + current = null; + if (result == null) + throw new NoSuchElementException(); + return result; + } + }; + } + } } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientFailureTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientFailureTest.java index 675067c3044..eada0ae3a5b 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientFailureTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientFailureTest.java @@ -74,7 +74,7 @@ public class HttpClientFailureTest startServer(new EmptyServerHandler()); final AtomicReference connectionRef = new AtomicReference<>(); - client = new HttpClient(new HttpClientTransportOverHTTP() + client = new HttpClient(new HttpClientTransportOverHTTP(1) { @Override protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise promise) @@ -83,15 +83,14 @@ public class HttpClientFailureTest connectionRef.set(connection); return connection; } - }, null); + }); client.start(); - assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .onRequestHeaders(request -> connectionRef.get().getEndPoint().close()) - .timeout(5, TimeUnit.SECONDS) - .send(); - }); + assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .onRequestHeaders(request -> connectionRef.get().getEndPoint().close()) + .timeout(5, TimeUnit.SECONDS) + .send()); DuplexConnectionPool connectionPool = (DuplexConnectionPool)connectionRef.get().getHttpDestination().getConnectionPool(); assertEquals(0, connectionPool.getConnectionCount()); @@ -105,7 +104,7 @@ public class HttpClientFailureTest startServer(new EmptyServerHandler()); final AtomicReference connectionRef = new AtomicReference<>(); - client = new HttpClient(new HttpClientTransportOverHTTP() + client = new HttpClient(new HttpClientTransportOverHTTP(1) { @Override protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise promise) @@ -114,7 +113,7 @@ public class HttpClientFailureTest connectionRef.set(connection); return connection; } - }, null); + }); client.start(); final CountDownLatch commitLatch = new CountDownLatch(1); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java index 9038ec52f95..8da2a30390b 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java @@ -18,14 +18,6 @@ package org.eclipse.jetty.client; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.IOException; import java.net.URLDecoder; import java.nio.ByteBuffer; @@ -34,7 +26,9 @@ import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -48,13 +42,20 @@ import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.IO; import org.hamcrest.Matchers; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ArgumentsSource; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class HttpClientRedirectTest extends AbstractHttpClientServerTest { @ParameterizedTest @@ -128,14 +129,13 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest { start(scenario, new RedirectHandler()); - ExecutionException x = assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .scheme(scenario.getScheme()) - .method(HttpMethod.DELETE) - .path("/301/localhost/done") - .timeout(5, TimeUnit.SECONDS) - .send(); - }); + ExecutionException x = assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scenario.getScheme()) + .method(HttpMethod.DELETE) + .path("/301/localhost/done") + .timeout(5, TimeUnit.SECONDS) + .send()); HttpResponseException xx = (HttpResponseException)x.getCause(); Response response = xx.getResponse(); assertNotNull(response); @@ -170,13 +170,12 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest start(scenario, new RedirectHandler()); client.setMaxRedirects(1); - ExecutionException x = assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .scheme(scenario.getScheme()) - .path("/303/localhost/302/localhost/done") - .timeout(5, TimeUnit.SECONDS) - .send(); - }); + ExecutionException x = assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scenario.getScheme()) + .path("/303/localhost/302/localhost/done") + .timeout(5, TimeUnit.SECONDS) + .send()); HttpResponseException xx = (HttpResponseException)x.getCause(); Response response = xx.getResponse(); assertNotNull(response); @@ -269,12 +268,11 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest @ArgumentsSource(ScenarioProvider.class) public void testRedirectWithWrongScheme(Scenario scenario) throws Exception { - start(scenario, new AbstractHandler() + start(scenario, new EmptyServerHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - baseRequest.setHandled(true); response.setStatus(303); response.setHeader("Location", "ssh://localhost:" + connector.getLocalPort() + "/path"); } @@ -439,12 +437,11 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest public void testRedirectWithCorruptedBody(Scenario scenario) throws Exception { byte[] bytes = "ok".getBytes(StandardCharsets.UTF_8); - start(scenario, new AbstractHandler() + start(scenario, new EmptyServerHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - baseRequest.setHandled(true); if (target.startsWith("/redirect")) { response.setStatus(HttpStatus.SEE_OTHER_303); @@ -471,6 +468,60 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest assertArrayEquals(bytes, response.getContent()); } + @ParameterizedTest + @ArgumentsSource(ScenarioProvider.class) + public void testRedirectToSameURL(Scenario scenario) throws Exception + { + start(scenario, new EmptyServerHandler() + { + @Override + protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) + { + response.setStatus(HttpStatus.SEE_OTHER_303); + response.setHeader(HttpHeader.LOCATION.asString(), request.getRequestURI()); + } + }); + + ExecutionException x = assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scenario.getScheme()) + .send()); + assertThat(x.getCause(), Matchers.instanceOf(HttpResponseException.class)); + } + + @ParameterizedTest + @ArgumentsSource(ScenarioProvider.class) + public void testInfiniteRedirectLoopMustTimeout(Scenario scenario) throws Exception + { + AtomicLong counter = new AtomicLong(); + start(scenario, new EmptyServerHandler() + { + @Override + protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) + { + try + { + Thread.sleep(200); + response.setStatus(HttpStatus.SEE_OTHER_303); + response.setHeader(HttpHeader.LOCATION.asString(), "/" + counter.getAndIncrement()); + } + catch (InterruptedException x) + { + throw new RuntimeException(x); + } + } + }); + + assertThrows(TimeoutException.class, () -> + { + client.setMaxRedirects(-1); + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scenario.getScheme()) + .timeout(1, TimeUnit.SECONDS) + .send(); + }); + } + private void testSameMethodRedirect(final Scenario scenario, final HttpMethod method, int redirectCode) throws Exception { testMethodRedirect(scenario, method, method, redirectCode); @@ -519,10 +570,10 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest assertEquals(200, response.getStatus()); } - private class RedirectHandler extends AbstractHandler + private class RedirectHandler extends EmptyServerHandler { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { @@ -551,10 +602,6 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest // Echo content back IO.copy(request.getInputStream(), response.getOutputStream()); } - finally - { - baseRequest.setHandled(true); - } } } } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java index 13c204f012a..f51f608556b 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java @@ -35,10 +35,12 @@ import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSocket; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ClientConnectionFactory; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.ssl.SslClientConnectionFactory; import org.eclipse.jetty.io.ssl.SslHandshakeListener; import org.eclipse.jetty.server.Handler; @@ -66,7 +68,7 @@ public class HttpClientTLSTest private ServerConnector connector; private HttpClient client; - private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception + private void startServer(SslContextFactory.Server sslContextFactory, Handler handler) throws Exception { ExecutorThreadPool serverThreads = new ExecutorThreadPool(); serverThreads.setName("server"); @@ -79,22 +81,37 @@ public class HttpClientTLSTest server.start(); } - private void startClient(SslContextFactory sslContextFactory) throws Exception + private void startClient(SslContextFactory.Client sslContextFactory) throws Exception { + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); + clientConnector.setSslContextFactory(sslContextFactory); QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(sslContextFactory); - client.setExecutor(clientThreads); + clientConnector.setExecutor(clientThreads); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); client.start(); } - private SslContextFactory createSslContextFactory() + private SslContextFactory.Server createServerSslContextFactory() + { + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); + configureSslContextFactory(sslContextFactory); + return sslContextFactory; + } + + private SslContextFactory.Client createClientSslContextFactory() + { + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + configureSslContextFactory(sslContextFactory); + sslContextFactory.setEndpointIdentificationAlgorithm(null); + return sslContextFactory; + } + + private void configureSslContextFactory(SslContextFactory sslContextFactory) { - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); - return sslContextFactory; } @AfterEach @@ -109,7 +126,7 @@ public class HttpClientTLSTest @Test public void testNoCommonTLSProtocol() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); serverTLSFactory.setIncludeProtocols("TLSv1.3"); startServer(serverTLSFactory, new EmptyServerHandler()); @@ -123,7 +140,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); clientTLSFactory.setIncludeProtocols("TLSv1.2"); startClient(clientTLSFactory); @@ -150,7 +167,7 @@ public class HttpClientTLSTest @Test public void testNoCommonTLSCiphers() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); serverTLSFactory.setIncludeCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA"); startServer(serverTLSFactory, new EmptyServerHandler()); @@ -164,7 +181,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); clientTLSFactory.setExcludeCipherSuites(".*_SHA$"); startClient(clientTLSFactory); @@ -191,7 +208,7 @@ public class HttpClientTLSTest @Test public void testMismatchBetweenTLSProtocolAndTLSCiphersOnServer() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); // TLS 1.1 protocol, but only TLS 1.2 ciphers. serverTLSFactory.setIncludeProtocols("TLSv1.1"); serverTLSFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); @@ -207,7 +224,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); startClient(clientTLSFactory); CountDownLatch clientLatch = new CountDownLatch(1); @@ -236,7 +253,7 @@ public class HttpClientTLSTest @Test public void testMismatchBetweenTLSProtocolAndTLSCiphersOnClient() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); startServer(serverTLSFactory, new EmptyServerHandler()); CountDownLatch serverLatch = new CountDownLatch(1); @@ -249,7 +266,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); // TLS 1.1 protocol, but only TLS 1.2 ciphers. clientTLSFactory.setIncludeProtocols("TLSv1.1"); clientTLSFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); @@ -278,7 +295,7 @@ public class HttpClientTLSTest @Test public void testHandshakeSucceeded() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); startServer(serverTLSFactory, new EmptyServerHandler()); CountDownLatch serverLatch = new CountDownLatch(1); @@ -291,7 +308,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); startClient(clientTLSFactory); CountDownLatch clientLatch = new CountDownLatch(1); @@ -317,7 +334,7 @@ public class HttpClientTLSTest @Test public void testHandshakeSucceededWithSessionResumption() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); startServer(serverTLSFactory, new EmptyServerHandler()); AtomicReference serverSession = new AtomicReference<>(); @@ -330,7 +347,7 @@ public class HttpClientTLSTest } }); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); startClient(clientTLSFactory); AtomicReference clientSession = new AtomicReference<>(); @@ -397,10 +414,10 @@ public class HttpClientTLSTest @Test public void testClientRawCloseDoesNotInvalidateSession() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); startServer(serverTLSFactory, new EmptyServerHandler()); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory clientTLSFactory = createClientSslContextFactory(); clientTLSFactory.start(); String host = "localhost"; @@ -452,13 +469,17 @@ public class HttpClientTLSTest @Test public void testServerRawCloseDetectedByClient() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory serverTLSFactory = createServerSslContextFactory(); serverTLSFactory.start(); try (ServerSocket server = new ServerSocket(0)) { + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(createSslContextFactory()) + clientConnector.setExecutor(clientThreads); + clientConnector.setSslContextFactory(createClientSslContextFactory()); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)) { @Override protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory) @@ -468,7 +489,6 @@ public class HttpClientTLSTest return ssl; } }; - client.setExecutor(clientThreads); client.start(); CountDownLatch latch = new CountDownLatch(1); @@ -522,10 +542,10 @@ public class HttpClientTLSTest @Test public void testHostNameVerificationFailure() throws Exception { - SslContextFactory serverTLSFactory = createSslContextFactory(); + SslContextFactory.Server serverTLSFactory = createServerSslContextFactory(); startServer(serverTLSFactory, new EmptyServerHandler()); - SslContextFactory clientTLSFactory = createSslContextFactory(); + SslContextFactory.Client clientTLSFactory = createClientSslContextFactory(); // Make sure the host name is not verified at the TLS level. clientTLSFactory.setEndpointIdentificationAlgorithm(null); // Add host name verification after the TLS handshake. diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index 161819348b0..e94411302c6 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -78,6 +78,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.AbstractConnection; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.jupiter.WorkDir; @@ -90,6 +91,7 @@ import org.eclipse.jetty.util.SocketAddressResolver; import org.eclipse.jetty.util.log.StacklessLogging; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -110,7 +112,6 @@ public class HttpClientTest extends AbstractHttpClientServerTest { public WorkDir testdir; - @ParameterizedTest @ArgumentsSource(ScenarioProvider.class) public void testStoppingClosesConnections(Scenario scenario) throws Exception @@ -186,7 +187,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.getOutputStream().write(data); baseRequest.setHandled(true); @@ -211,7 +212,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); ServletOutputStream output = response.getOutputStream(); @@ -244,7 +245,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); ServletOutputStream output = response.getOutputStream(); @@ -281,7 +282,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -314,7 +315,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -348,7 +349,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); consume(request.getInputStream(), true); @@ -380,7 +381,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); consume(request.getInputStream(), true); @@ -411,7 +412,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); consume(request.getInputStream(), true); @@ -492,7 +493,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { if (target.endsWith("/one")) baseRequest.getHttpChannel().getEndPoint().close(); @@ -611,7 +612,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { // Echo back IO.copy(request.getInputStream(), response.getOutputStream()); @@ -633,7 +634,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest @Override public Iterator iterator() { - return new Iterator() + return new Iterator<>() { @Override public boolean hasNext() @@ -705,7 +706,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException { try { @@ -721,13 +722,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest final String host = "localhost"; final int port = connector.getLocalPort(); - assertThrows(TimeoutException.class, ()->{ - client.newRequest(host, port) - .scheme(scenario.getScheme()) - .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) - .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) - .send(); - }); + assertThrows(TimeoutException.class, () -> + client.newRequest(host, port) + .scheme(scenario.getScheme()) + .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) + .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) + .send()); // Make another request without specifying the idle timeout, should not fail ContentResponse response = client.newRequest(host, port) @@ -741,6 +741,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest @ParameterizedTest @ArgumentsSource(ScenarioProvider.class) + @Tag("ipv6") public void testSendToIPv6Address(Scenario scenario) throws Exception { start(scenario, new EmptyServerHandler()); @@ -762,7 +763,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); response.setHeader(headerName, "X"); @@ -820,7 +821,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.getOutputStream().write(new byte[length]); @@ -881,14 +882,14 @@ public class HttpClientTest extends AbstractHttpClientServerTest public void testConnectHostWithMultipleAddresses(Scenario scenario) throws Exception { startServer(scenario, new EmptyServerHandler()); - startClient(scenario, null, client -> + startClient(scenario, client -> { client.setSocketAddressResolver(new SocketAddressResolver.Async(client.getExecutor(), client.getScheduler(), 5000) { @Override public void resolve(String host, int port, Promise> promise) { - super.resolve(host, port, new Promise>() + super.resolve(host, port, new Promise<>() { @Override public void succeeded(List result) @@ -924,7 +925,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); ArrayList userAgents = Collections.list(request.getHeaders("User-Agent")); @@ -958,7 +959,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); ArrayList userAgents = Collections.list(request.getHeaders("User-Agent")); @@ -1160,7 +1161,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.getOutputStream().write(content); @@ -1204,7 +1205,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); assertEquals(host, request.getServerName()); @@ -1226,7 +1227,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { // Send the headers at this point, then write the content byte[] content = "TEST".getBytes("UTF-8"); @@ -1254,7 +1255,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { // Send the headers at this point, then write the content response.flushBuffer(); @@ -1312,7 +1313,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); request.startAsync(); @@ -1343,9 +1344,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest { Assumptions.assumeTrue(HttpScheme.HTTP.is(scenario.getScheme())); - ExecutionException e = assertThrows(ExecutionException.class, ()->{ - testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 1024); - }); + ExecutionException e = assertThrows(ExecutionException.class, () -> + testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 1024)); assertThat(e.getCause(), instanceOf(BadMessageException.class)); assertThat(e.getCause().getMessage(), containsString("Unknown content")); @@ -1355,9 +1355,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest @ArgumentsSource(NonSslScenarioProvider.class) public void testBigContentDelimitedByEOFWithSlowRequestHTTP10(Scenario scenario) throws Exception { - ExecutionException e = assertThrows(ExecutionException.class, ()->{ - testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 128 * 1024); - }); + ExecutionException e = assertThrows(ExecutionException.class, () -> + testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 128 * 1024)); assertThat(e.getCause(), instanceOf(BadMessageException.class)); assertThat(e.getCause().getMessage(), containsString("Unknown content")); @@ -1391,7 +1390,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); // Send Connection: close to avoid that the server chunks the content with HTTP 1.1. @@ -1427,7 +1426,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { int count = requests.incrementAndGet(); if (count == maxRetries) @@ -1456,7 +1455,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); ServletOutputStream output = response.getOutputStream(); @@ -1506,14 +1505,16 @@ public class HttpClientTest extends AbstractHttpClientServerTest startServer(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); } }); final AtomicBoolean open = new AtomicBoolean(); - client = new HttpClient(new HttpClientTransportOverHTTP() + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSslContextFactory(scenario.newClientSslContextFactory()); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector) { @Override protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise promise) @@ -1528,7 +1529,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest } }; } - }, scenario.newSslContextFactory()); + }); client.start(); final CountDownLatch latch = new CountDownLatch(2); @@ -1610,12 +1611,13 @@ public class HttpClientTest extends AbstractHttpClientServerTest @ParameterizedTest @ArgumentsSource(ScenarioProvider.class) + @Tag("ipv6") public void test_IPv6_Host(Scenario scenario) throws Exception { start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.setContentType("text/plain"); @@ -1690,7 +1692,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(scenario, new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); assertThat(request.getHeader("Host"), Matchers.notNullValue()); @@ -1716,7 +1718,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest try (ServerSocket server = new ServerSocket(0)) { int idleTimeout = 2000; - startClient(scenario, null, httpClient -> + startClient(scenario, httpClient -> { httpClient.setMaxConnectionsPerDestination(1); httpClient.setIdleTimeout(idleTimeout); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java index 8523d0b2fc6..912234995bb 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java @@ -18,13 +18,6 @@ package org.eclipse.jetty.client; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -52,13 +45,22 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.Fields; import org.eclipse.jetty.util.URIUtil; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ArgumentsSource; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class HttpClientURITest extends AbstractHttpClientServerTest { @ParameterizedTest @ArgumentsSource(ScenarioProvider.class) + @Tag("ipv6") public void testIPv6Host(Scenario scenario) throws Exception { start(scenario, new EmptyServerHandler()); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientUploadDuringServerShutdown.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientUploadDuringServerShutdown.java index d8a0e0d48cb..148ecd6156b 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientUploadDuringServerShutdown.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientUploadDuringServerShutdown.java @@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -65,7 +64,7 @@ public class HttpClientUploadDuringServerShutdown server.setHandler(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); byte[] buffer = new byte[1024]; @@ -103,7 +102,7 @@ public class HttpClientUploadDuringServerShutdown { QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - HttpClient client = new HttpClient(new HttpClientTransportOverHTTP(2), null); + HttpClient client = new HttpClient(new HttpClientTransportOverHTTP(2)); client.setMaxConnectionsPerDestination(2); client.setIdleTimeout(10000); client.setExecutor(clientThreads); @@ -142,7 +141,7 @@ public class HttpClientUploadDuringServerShutdown server.setHandler(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); endPointRef.set(baseRequest.getHttpChannel().getEndPoint()); @@ -210,7 +209,7 @@ public class HttpClientUploadDuringServerShutdown } }; } - }, null); + }); client.setIdleTimeout(10000); client.setExecutor(clientThreads); client.start(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java index 97d2006dd93..f4b2fbdf2a1 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpConnectionLifecycleTest.java @@ -53,9 +53,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest { @Override - public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport) + public HttpClient newHttpClient(HttpClientTransport transport) { - HttpClient client = super.newHttpClient(scenario, transport); + HttpClient client = super.newHttpClient(transport); client.setStrictEventOrdering(false); return client; } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/InsufficientThreadsDetectionTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/InsufficientThreadsDetectionTest.java index 86051d6f8d7..2d396121628 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/InsufficientThreadsDetectionTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/InsufficientThreadsDetectionTest.java @@ -30,7 +30,7 @@ public class InsufficientThreadsDetectionTest public void testInsufficientThreads() { QueuedThreadPool clientThreads = new QueuedThreadPool(1); - HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(1), null); + HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(1)); httpClient.setExecutor(clientThreads); assertThrows(IllegalStateException.class, httpClient::start); } @@ -39,14 +39,14 @@ public class InsufficientThreadsDetectionTest public void testInsufficientThreadsForMultipleHttpClients() throws Exception { QueuedThreadPool clientThreads = new QueuedThreadPool(3); - HttpClient httpClient1 = new HttpClient(new HttpClientTransportOverHTTP(1), null); + HttpClient httpClient1 = new HttpClient(new HttpClientTransportOverHTTP(1)); httpClient1.setExecutor(clientThreads); httpClient1.start(); assertThrows(IllegalStateException.class, () -> { // Share the same thread pool with another instance. - HttpClient httpClient2 = new HttpClient(new HttpClientTransportOverHTTP(1), null); + HttpClient httpClient2 = new HttpClient(new HttpClientTransportOverHTTP(1)); httpClient2.setExecutor(clientThreads); httpClient2.start(); }); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/LivelockTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/LivelockTest.java index 172c9fdd007..1440e975427 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/LivelockTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/LivelockTest.java @@ -93,7 +93,7 @@ public class LivelockTest int count = 5; HttpClientTransport transport = new HttpClientTransportOverHTTP(1); - client = new HttpClient(transport, null); + client = new HttpClient(transport); client.setMaxConnectionsPerDestination(2 * count); client.setMaxRequestsQueuedPerDestination(2 * count); client.setSocketAddressResolver(new SocketAddressResolver.Sync()); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyConfigurationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyConfigurationTest.java index 2b112bcd9f9..6827fca3db9 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyConfigurationTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyConfigurationTest.java @@ -18,12 +18,12 @@ package org.eclipse.jetty.client; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - public class ProxyConfigurationTest { @Test @@ -68,6 +68,7 @@ public class ProxyConfigurationTest } @Test + @Tag("ipv6") public void testProxyMatchesWithIncludesAndExcludesIPv6() throws Exception { HttpProxy proxy = new HttpProxy("host", 0); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ServerConnectionCloseTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ServerConnectionCloseTest.java index 54f5f7ba1f9..2869e72b293 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ServerConnectionCloseTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ServerConnectionCloseTest.java @@ -44,7 +44,7 @@ public class ServerConnectionCloseTest { QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(new HttpClientTransportOverHTTP(1), null); + client = new HttpClient(new HttpClientTransportOverHTTP(1)); client.setExecutor(clientThreads); client.start(); } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/TLSServerConnectionCloseTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/TLSServerConnectionCloseTest.java index 20bb341c3ac..9568b69eb28 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/TLSServerConnectionCloseTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/TLSServerConnectionCloseTest.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.jupiter.api.AfterEach; @@ -47,15 +48,20 @@ public class TLSServerConnectionCloseTest private void startClient() throws Exception { - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); + + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + sslContextFactory.setEndpointIdentificationAlgorithm(null); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); + clientConnector.setSslContextFactory(sslContextFactory); QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(new HttpClientTransportOverHTTP(1), sslContextFactory); - client.setExecutor(clientThreads); + clientConnector.setExecutor(clientThreads); + + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); client.start(); } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java index 27b12989c41..8df67a63849 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ValidatingConnectionPoolTest.java @@ -42,13 +42,13 @@ import org.junit.jupiter.params.provider.ArgumentsSource; public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest { @Override - public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport) + public HttpClient newHttpClient(HttpClientTransport transport) { long timeout = 1000; transport.setConnectionPoolFactory(destination -> new ValidatingConnectionPool(destination, destination.getHttpClient().getMaxConnectionsPerDestination(), destination, destination.getHttpClient().getScheduler(), timeout)); - return super.newHttpClient(scenario, transport); + return super.newHttpClient(transport); } @ParameterizedTest diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpDestinationOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpDestinationOverHTTPTest.java index e595e7d4456..d2ecbe95d57 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpDestinationOverHTTPTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpDestinationOverHTTPTest.java @@ -186,7 +186,7 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest { startServer(scenario, new EmptyServerHandler()); long idleTimeout = 1000; - startClient(scenario, null, httpClient -> httpClient.setIdleTimeout(idleTimeout)); + startClient(scenario, httpClient -> httpClient.setIdleTimeout(idleTimeout)); try(HttpDestination destination = new DuplexHttpDestination(client, new Origin("http", "localhost", connector.getLocalPort()))) { diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/NeedWantClientAuthTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/NeedWantClientAuthTest.java index 59fd76f42cd..ab32beb6b9f 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/NeedWantClientAuthTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/NeedWantClientAuthTest.java @@ -18,11 +18,6 @@ package org.eclipse.jetty.client.ssl; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.security.cert.Certificate; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -34,7 +29,9 @@ import javax.net.ssl.SSLSession; import org.eclipse.jetty.client.EmptyServerHandler; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.ssl.SslHandshakeListener; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; @@ -43,9 +40,13 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterEach; - import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * In order to work, client authentication needs a certificate * signed by a CA that also signed the server certificate. @@ -59,7 +60,7 @@ public class NeedWantClientAuthTest private ServerConnector connector; private HttpClient client; - private void startServer(SslContextFactory sslContextFactory, Handler handler) throws Exception + private void startServer(SslContextFactory.Server sslContextFactory, Handler handler) throws Exception { QueuedThreadPool serverThreads = new QueuedThreadPool(); serverThreads.setName("server"); @@ -72,19 +73,21 @@ public class NeedWantClientAuthTest server.start(); } - private void startClient(SslContextFactory sslContextFactory) throws Exception + private void startClient(SslContextFactory.Client sslContextFactory) throws Exception { + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(sslContextFactory); - client.setExecutor(clientThreads); + clientConnector.setExecutor(clientThreads); + clientConnector.setSslContextFactory(sslContextFactory); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); client.start(); } - private SslContextFactory createSslContextFactory() + private SslContextFactory.Server createServerSslContextFactory() { - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); return sslContextFactory; @@ -102,11 +105,11 @@ public class NeedWantClientAuthTest @Test public void testWantClientAuthWithoutAuth() throws Exception { - SslContextFactory serverSSL = createSslContextFactory(); + SslContextFactory.Server serverSSL = createServerSslContextFactory(); serverSSL.setWantClientAuth(true); startServer(serverSSL, new EmptyServerHandler()); - SslContextFactory clientSSL = new SslContextFactory(true); + SslContextFactory.Client clientSSL = new SslContextFactory.Client(true); startClient(clientSSL); ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort()) @@ -119,7 +122,7 @@ public class NeedWantClientAuthTest @Test public void testWantClientAuthWithAuth() throws Exception { - SslContextFactory serverSSL = createSslContextFactory(); + SslContextFactory.Server serverSSL = createServerSslContextFactory(); serverSSL.setWantClientAuth(true); startServer(serverSSL, new EmptyServerHandler()); CountDownLatch handshakeLatch = new CountDownLatch(1); @@ -143,7 +146,7 @@ public class NeedWantClientAuthTest } }); - SslContextFactory clientSSL = new SslContextFactory(true); + SslContextFactory.Client clientSSL = new SslContextFactory.Client(true); clientSSL.setKeyStorePath("src/test/resources/client_keystore.jks"); clientSSL.setKeyStorePassword("storepwd"); startClient(clientSSL); @@ -166,11 +169,11 @@ public class NeedWantClientAuthTest // The server still sends bad_certificate to the client, but the client handshake has already // completed successfully its TLS handshake. - SslContextFactory serverSSL = createSslContextFactory(); + SslContextFactory.Server serverSSL = createServerSslContextFactory(); serverSSL.setNeedClientAuth(true); startServer(serverSSL, new EmptyServerHandler()); - SslContextFactory clientSSL = new SslContextFactory(true); + SslContextFactory.Client clientSSL = new SslContextFactory.Client(true); startClient(clientSSL); CountDownLatch handshakeLatch = new CountDownLatch(1); client.addBean(new SslHandshakeListener() @@ -210,7 +213,7 @@ public class NeedWantClientAuthTest @Test public void testNeedClientAuthWithAuth() throws Exception { - SslContextFactory serverSSL = createSslContextFactory(); + SslContextFactory.Server serverSSL = createServerSslContextFactory(); serverSSL.setNeedClientAuth(true); startServer(serverSSL, new EmptyServerHandler()); CountDownLatch handshakeLatch = new CountDownLatch(1); @@ -234,7 +237,7 @@ public class NeedWantClientAuthTest } }); - SslContextFactory clientSSL = new SslContextFactory(true); + SslContextFactory.Client clientSSL = new SslContextFactory.Client(true); clientSSL.setKeyStorePath("src/test/resources/client_keystore.jks"); clientSSL.setKeyStorePassword("storepwd"); startClient(clientSSL); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java index 836c935c002..9bcdedbd375 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java @@ -38,9 +38,11 @@ import javax.net.ssl.SSLSocket; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.AfterEach; @@ -61,7 +63,7 @@ public class SslBytesClientTest extends SslBytesTest { private ExecutorService threadPool; private HttpClient client; - private SslContextFactory sslContextFactory; + private SslContextFactory.Client sslContextFactory; private SSLServerSocket acceptor; private SimpleProxy proxy; @@ -70,8 +72,11 @@ public class SslBytesClientTest extends SslBytesTest { threadPool = Executors.newCachedThreadPool(); - sslContextFactory = new SslContextFactory(true); - client = new HttpClient(sslContextFactory); + ClientConnector clientConnector = new ClientConnector(); + clientConnector.setSelectors(1); + sslContextFactory = new SslContextFactory.Client(true); + clientConnector.setSslContextFactory(sslContextFactory); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); client.setMaxConnectionsPerDestination(1); File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); @@ -243,7 +248,7 @@ public class SslBytesClientTest extends SslBytesTest // Trigger a read to have the server write the final renegotiation steps server.setSoTimeout(100); - assertThrows(SocketTimeoutException.class, ()->serverInput.read()); + assertThrows(SocketTimeoutException.class, () -> serverInput.read()); // Renegotiation Handshake record = proxy.readFromServer(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java index 1b16f72befd..874718cb8c9 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java @@ -100,7 +100,7 @@ public class SslBytesServerTest extends SslBytesTest private final int idleTimeout = 2000; private ExecutorService threadPool; private Server server; - private SslContextFactory sslContextFactory; + private SslContextFactory.Server sslContextFactory; private int serverPort; private SSLContext sslContext; private SimpleProxy proxy; @@ -119,7 +119,7 @@ public class SslBytesServerTest extends SslBytesTest serverEndPoint.set(null); File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); - sslContextFactory = new SslContextFactory(); + sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); sslContextFactory.setKeyStorePassword("storepwd"); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslConnectionTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslConnectionTest.java index cb657274128..c0952cebf60 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslConnectionTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslConnectionTest.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.client.ssl; -import static org.junit.jupiter.api.Assertions.assertThrows; - import java.io.File; import java.nio.ByteBuffer; @@ -36,16 +34,17 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class SslConnectionTest { @Test public void testSslConnectionClosedBeforeFill() throws Exception { File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); - SslContextFactory sslContextFactory = new SslContextFactory(); + SslContextFactory sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.start(); diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardDeployer.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardDeployer.java index dd58166c7be..5fa840a794a 100644 --- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardDeployer.java +++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardDeployer.java @@ -22,6 +22,7 @@ import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.Callback; public class StandardDeployer implements AppLifeCycle.Binding { @@ -37,9 +38,10 @@ public class StandardDeployer implements AppLifeCycle.Binding { ContextHandler handler = app.getContextHandler(); if (handler == null) - { throw new NullPointerException("No Handler created for App: " + app); - } - app.getDeploymentManager().getContexts().addHandler(handler); + + Callback.Completable blocker = new Callback.Completable(); + app.getDeploymentManager().getContexts().deployHandler(handler, blocker); + blocker.get(); } } diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardUndeployer.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardUndeployer.java index ad5b0377799..6502381cbe0 100644 --- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardUndeployer.java +++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/bindings/StandardUndeployer.java @@ -21,17 +21,12 @@ package org.eclipse.jetty.deploy.bindings; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.graph.Node; -import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.HandlerCollection; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.Callback; public class StandardUndeployer implements AppLifeCycle.Binding { - private static final Logger LOG = Log.getLogger(StandardUndeployer.class); - @Override public String[] getBindingTargets() { @@ -42,33 +37,11 @@ public class StandardUndeployer implements AppLifeCycle.Binding @Override public void processBinding(Node node, App app) throws Exception { - ContextHandler handler = app.getContextHandler(); - ContextHandlerCollection chcoll = app.getDeploymentManager().getContexts(); - - recursiveRemoveContext(chcoll,handler); - } - - private void recursiveRemoveContext(HandlerCollection coll, ContextHandler context) - { - Handler children[] = coll.getHandlers(); - int originalCount = children.length; - - for (int i = 0, n = children.length; i < n; i++) - { - Handler child = children[i]; - LOG.debug("Child handler {}",child); - if (child.equals(context)) - { - LOG.debug("Removing handler {}",child); - coll.removeHandler(child); - child.destroy(); - if (LOG.isDebugEnabled()) - LOG.debug("After removal: {} (originally {})",coll.getHandlers().length,originalCount); - } - else if (child instanceof HandlerCollection) - { - recursiveRemoveContext((HandlerCollection)child,context); - } - } + ContextHandlerCollection contexts = app.getDeploymentManager().getContexts(); + ContextHandler context = app.getContextHandler(); + Callback.Completable blocker = new Callback.Completable(); + contexts.undeployHandler(context, blocker); + blocker.get(); + context.destroy(); } } diff --git a/jetty-documentation/src/main/asciidoc/administration/jmx/using-jmx.adoc b/jetty-documentation/src/main/asciidoc/administration/jmx/using-jmx.adoc index e650ecb0f8b..3a6756935a9 100644 --- a/jetty-documentation/src/main/asciidoc/administration/jmx/using-jmx.adoc +++ b/jetty-documentation/src/main/asciidoc/administration/jmx/using-jmx.adoc @@ -290,8 +290,8 @@ Similarly, in code: [source, java, subs="{sub-order}"] ---- -SslContextFactory sslContextFactory = new SslContextFactory(); -sslContextFactory.setKeyStorePath(); +SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); +sslContextFactory.setKeyStorePath("/path/to/keystore"); sslContextFactory.setKeyStorePassword("secret"); JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi"); diff --git a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-connectors.adoc b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-connectors.adoc index 8b2a1864a28..f0adcb24ecd 100644 --- a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-connectors.adoc +++ b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-connectors.adoc @@ -472,7 +472,7 @@ This adds a `SecureRequestCustomizer` which adds SSL Session IDs and certificate ==== SSL Context Configuration The SSL/TLS connectors for HTTPS and HTTP/2 require a certificate to establish a secure connection. -Jetty holds certificates in standard JVM keystores and are configured as keystore and truststores on a link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[`SslContextFactory`] instance that is injected into an link:{JDURL}/org/eclipse/jetty/server/SslConnectionFactory.html[`SslConnectionFactory`] instance. +Jetty holds certificates in standard JVM keystores and are configured as keystore and truststores on a link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.Server.html[`SslContextFactory.Server`] instance that is injected into an link:{JDURL}/org/eclipse/jetty/server/SslConnectionFactory.html[`SslConnectionFactory`] instance. An example using the keystore distributed with Jetty (containing a self signed test certificate) is in link:{GITBROWSEURL}/jetty-server/src/main/config/etc/jetty-https.xml[`jetty-https.xml`]. Read more about SSL keystores in link:#configuring-ssl[Configuring SSL]. diff --git a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc index 6abde51fe5f..f2702996b7e 100644 --- a/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc +++ b/jetty-documentation/src/main/asciidoc/configuring/connectors/configuring-ssl.adoc @@ -55,9 +55,8 @@ You can re-enable these by re-declaring the ciphers you want excluded in code: [source, java, subs="{sub-order}"] ---- -SslContextFactory sslContextFactory = new SslContextFactory(); -sslContextFactory.setExcludeCipherSuites( - "^.*_(MD5|SHA|SHA1)$"); +SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); +sslContextFactory.setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$"); ---- If, after making these changes, you still have issues using these ciphers they are likely being blocked at the JVM level. @@ -664,7 +663,7 @@ the other is `$JETTY/etc/truststore` which contains intermediary CA and root CA. [[configuring-sslcontextfactory]] ==== Configuring the Jetty SslContextFactory -The generated SSL certificates from above are held in the key store are configured in an instance of link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[SslContextFactory] object. +The generated SSL certificates from above are held in the key store are configured in an instance of link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.Server.html[SslContextFactory.Server] object. The `SslContextFactory` is responsible for: @@ -679,9 +678,9 @@ The `SslContextFactory` is responsible for: * https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol[OCSP] Support * Client Authentication Support -For Jetty Connectors, the configured `SslContextFactory` is injected into a specific ServerConnector `SslConnectionFactory`. +For Jetty Connectors, the configured `SslContextFactory.Server` is injected into a specific ServerConnector `SslConnectionFactory`. -For Jetty Clients, the various constructors support using a configured `SslContextFactory`. +For Jetty Clients, the various constructors support using a configured `SslContextFactory.Client`. While the `SslContextFactory` can operate without a keystore (this mode is most suitable for the various Jetty Clients) it is best practice to at least configure the keystore being used. @@ -729,7 +728,7 @@ Implementing Conscrypt for the link:{GITBROWSEURL}/jetty-alpn/jetty-alpn-conscry ... Security.addProvider(new OpenSSLProvider()); ... -SslContextFactory sslContextFactory = new SslContextFactory(); +SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("path/to/keystore"); sslContextFactory.setKeyStorePassword("CleverKeyStorePassword"); sslContextFactory.setKeyManagerPassword("OBF:VerySecretManagerPassword"); @@ -790,7 +789,7 @@ To do this, first create a new `${jetty.base}/etc/tweak-ssl.xml` file (this can - + diff --git a/jetty-documentation/src/main/asciidoc/development/clients/http/http-client-intro.adoc b/jetty-documentation/src/main/asciidoc/development/clients/http/http-client-intro.adoc index de8d0567f31..429f0444763 100644 --- a/jetty-documentation/src/main/asciidoc/development/clients/http/http-client-intro.adoc +++ b/jetty-documentation/src/main/asciidoc/development/clients/http/http-client-intro.adoc @@ -75,13 +75,13 @@ There are several reasons for having multiple `HttpClient` instances including, When you create a `HttpClient` instance using the parameterless constructor, you will only be able to perform plain HTTP requests and you will not be able to perform HTTPS requests. -In order to perform HTTPS requests, you should create first a link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.html[`SslContextFactory`], configure it, and pass it to the `HttpClient` constructor. +In order to perform HTTPS requests, you should create first a link:{JDURL}/org/eclipse/jetty/util/ssl/SslContextFactory.Client.html[`SslContextFactory.Client`], configure it, and pass it to the `HttpClient` constructor. When created with a `SslContextFactory`, the `HttpClient` will be able to perform both HTTP and HTTPS requests to any domain. [source, java, subs="{sub-order}"] ---- // Instantiate and configure the SslContextFactory -SslContextFactory sslContextFactory = new SslContextFactory(); +SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); // Instantiate HttpClient with the SslContextFactory HttpClient httpClient = new HttpClient(sslContextFactory); diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java index 59d7b9fa8d7..2409759da8a 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java @@ -116,7 +116,7 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent String value = config.getInitParameter("selectors"); if (value != null) selectors = Integer.parseInt(value); - return new HttpClient(new ProxyHttpClientTransportOverFCGI(selectors, scriptRoot), null); + return new HttpClient(new ProxyHttpClientTransportOverFCGI(selectors, scriptRoot)); } @Override diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/AbstractHttpClientServerTest.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/AbstractHttpClientServerTest.java index 37dc731578c..b4fb17beb11 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/AbstractHttpClientServerTest.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/AbstractHttpClientServerTest.java @@ -76,7 +76,7 @@ public abstract class AbstractHttpClientServerTest connectionLeaks.incrementAndGet(); } }); - client = new HttpClient(transport, null); + client = new HttpClient(transport); client.setExecutor(executor); if (clientBufferPool == null) clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/ExternalFastCGIServerTest.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/ExternalFastCGIServerTest.java index 933acc70f6a..64e53da2d3d 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/ExternalFastCGIServerTest.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/ExternalFastCGIServerTest.java @@ -40,7 +40,7 @@ public class ExternalFastCGIServerTest { // Assume a FastCGI server is listening on localhost:9000 - HttpClient client = new HttpClient(new HttpClientTransportOverFCGI("/var/www/php-fcgi"), null); + HttpClient client = new HttpClient(new HttpClientTransportOverFCGI("/var/www/php-fcgi")); client.start(); ContentResponse response = client.newRequest("localhost", 9000) diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java index 27a7ef955dc..a30ed2370a3 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java @@ -18,14 +18,6 @@ package org.eclipse.jetty.fcgi.server; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.EOFException; import java.io.IOException; import java.net.URI; @@ -49,7 +41,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.util.BytesContentProvider; import org.eclipse.jetty.client.util.DeferredContentProvider; import org.eclipse.jetty.client.util.FutureResponseListener; @@ -59,10 +50,18 @@ import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.log.StacklessLogging; - +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class HttpClientTest extends AbstractHttpClientServerTest { @Test @@ -85,7 +84,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.getOutputStream().write(data); baseRequest.setHandled(true); @@ -113,7 +112,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { // Setting the Content-Length triggers the HTTP // content mode for response content parsing, @@ -142,7 +141,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); ServletOutputStream output = response.getOutputStream(); @@ -174,7 +173,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); ServletOutputStream output = response.getOutputStream(); @@ -210,7 +209,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -241,7 +240,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -273,7 +272,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -306,7 +305,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); String value = request.getParameter(paramName); @@ -340,16 +339,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new EmptyServerHandler()); ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort()) - .onRequestContent(new Request.ContentListener() + .onRequestContent((request, buffer) -> { - @Override - public void onContent(Request request, ByteBuffer buffer) - { - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - if (!Arrays.equals(content, bytes)) - request.abort(new Exception()); - } + byte[] bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + if (!Arrays.equals(content, bytes)) + request.abort(new Exception()); }) .content(new BytesContentProvider(content)) .timeout(5, TimeUnit.SECONDS) @@ -366,16 +361,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest final AtomicInteger progress = new AtomicInteger(); ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort()) - .onRequestContent(new Request.ContentListener() + .onRequestContent((request, buffer) -> { - @Override - public void onContent(Request request, ByteBuffer buffer) - { - byte[] bytes = new byte[buffer.remaining()]; - assertEquals(1, bytes.length); - buffer.get(bytes); - assertEquals(bytes[0], progress.getAndIncrement()); - } + byte[] bytes = new byte[buffer.remaining()]; + assertEquals(1, bytes.length); + buffer.get(bytes); + assertEquals(bytes[0], progress.getAndIncrement()); }) .content(new BytesContentProvider(new byte[]{0}, new byte[]{1}, new byte[]{2}, new byte[]{3}, new byte[]{4})) .timeout(5, TimeUnit.SECONDS) @@ -398,7 +389,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.setHeader("Content-Encoding", "gzip"); @@ -425,7 +416,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException { try { @@ -441,13 +432,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest final String host = "localhost"; final int port = connector.getLocalPort(); - assertThrows(TimeoutException.class, ()->{ - client.newRequest(host, port) - .scheme(scheme) - .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) - .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) - .send(); - }); + assertThrows(TimeoutException.class, () -> + client.newRequest(host, port) + .scheme(scheme) + .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) + .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) + .send()); // Make another request without specifying the idle timeout, should not fail ContentResponse response = client.newRequest(host, port) @@ -466,7 +456,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException { try { @@ -482,13 +472,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest connector.setIdleTimeout(idleTimeout); - ExecutionException x = assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .scheme(scheme) - .idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS) - .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) - .send(); - }); + ExecutionException x = assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scheme) + .idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS) + .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) + .send()); assertThat(x.getCause(), instanceOf(EOFException.class)); connector.setIdleTimeout(5 * idleTimeout); @@ -505,6 +494,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest } @Test + @Tag("ipv6") public void testSendToIPv6Address() throws Exception { start(new EmptyServerHandler()); @@ -525,7 +515,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.getOutputStream().write(new byte[length]); @@ -562,7 +552,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); request.startAsync(); @@ -573,14 +563,10 @@ public class HttpClientTest extends AbstractHttpClientServerTest final CountDownLatch completeLatch = new CountDownLatch(1); client.newRequest("localhost", connector.getLocalPort()) .scheme(scheme) - .send(new Response.CompleteListener() + .send(result -> { - @Override - public void onComplete(Result result) - { - if (result.isFailed()) - completeLatch.countDown(); - } + if (result.isFailed()) + completeLatch.countDown(); }); assertTrue(latch.await(5, TimeUnit.SECONDS)); @@ -597,7 +583,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); // Promise some content, then flush the headers, then fail to send the content. @@ -609,12 +595,11 @@ public class HttpClientTest extends AbstractHttpClientServerTest try (StacklessLogging ignore = new StacklessLogging(org.eclipse.jetty.server.HttpChannel.class)) { - assertThrows(ExecutionException.class, () -> { - client.newRequest("localhost", connector.getLocalPort()) - .scheme(scheme) - .timeout(60, TimeUnit.SECONDS) - .send(); - }); + assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .scheme(scheme) + .timeout(60, TimeUnit.SECONDS) + .send()); } } @@ -637,7 +622,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.setHeader("Connection", "close"); @@ -667,7 +652,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest start(new AbstractHandler() { @Override - public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { ServletOutputStream output = response.getOutputStream(); output.write(65); @@ -682,24 +667,13 @@ public class HttpClientTest extends AbstractHttpClientServerTest final CountDownLatch completeLatch = new CountDownLatch(1); client.newRequest("localhost", connector.getLocalPort()) .scheme(scheme) - .onResponseContentAsync(new Response.AsyncContentListener() + .onResponseContentAsync((response, content, callback) -> { - @Override - public void onContent(Response response, ByteBuffer content, Callback callback) - { - contentCount.incrementAndGet(); - callbackRef.set(callback); - contentLatch.get().countDown(); - } + contentCount.incrementAndGet(); + callbackRef.set(callback); + contentLatch.get().countDown(); }) - .send(new Response.CompleteListener() - { - @Override - public void onComplete(Result result) - { - completeLatch.countDown(); - } - }); + .send(result -> completeLatch.countDown()); assertTrue(contentLatch.get().await(5, TimeUnit.SECONDS)); Callback callback = callbackRef.get(); diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/DrupalHTTP2FastCGIProxyServer.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/DrupalHTTP2FastCGIProxyServer.java index 67568980f73..23a89cabada 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/DrupalHTTP2FastCGIProxyServer.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/DrupalHTTP2FastCGIProxyServer.java @@ -36,8 +36,7 @@ public class DrupalHTTP2FastCGIProxyServer { public static void main(String[] args) throws Exception { - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/TryFilesFilterTest.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/TryFilesFilterTest.java index 3e52405c11d..e62eb00ec62 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/TryFilesFilterTest.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/TryFilesFilterTest.java @@ -18,20 +18,17 @@ package org.eclipse.jetty.fcgi.server.proxy; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; import java.util.EnumSet; import javax.servlet.DispatcherType; -import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.FilterHolder; @@ -41,6 +38,9 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class TryFilesFilterTest { private Server server; @@ -55,13 +55,10 @@ public class TryFilesFilterTest connector = new ServerConnector(server); server.addConnector(connector); - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); - sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); - sslContextFactory.setKeyStorePassword("storepwd"); - sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); - sslContextFactory.setTrustStorePassword("storepwd"); - sslConnector = new ServerConnector(server, sslContextFactory); + SslContextFactory.Server serverSslContextFactory = new SslContextFactory.Server(); + serverSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); + serverSslContextFactory.setKeyStorePassword("storepwd"); + sslConnector = new ServerConnector(server, serverSslContextFactory); server.addConnector(sslConnector); ServletContextHandler context = new ServletContextHandler(server, "/"); @@ -72,7 +69,15 @@ public class TryFilesFilterTest context.addServlet(new ServletHolder(servlet), "/*"); - client = new HttpClient(sslContextFactory); + ClientConnector clientConnector = new ClientConnector(); + SslContextFactory.Client clientSslContextFactory = new SslContextFactory.Client(); + clientSslContextFactory.setEndpointIdentificationAlgorithm(null); + clientSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); + clientSslContextFactory.setKeyStorePassword("storepwd"); + clientSslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); + clientSslContextFactory.setTrustStorePassword("storepwd"); + clientConnector.setSslContextFactory(clientSslContextFactory); + client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector)); server.addBean(client); server.start(); @@ -91,7 +96,7 @@ public class TryFilesFilterTest prepare(new HttpServlet() { @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { assertTrue("https".equalsIgnoreCase(req.getScheme())); assertTrue(req.isSecure()); diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/WordPressHTTP2FastCGIProxyServer.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/WordPressHTTP2FastCGIProxyServer.java index c10e94c1782..c5fa6782b18 100644 --- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/WordPressHTTP2FastCGIProxyServer.java +++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/proxy/WordPressHTTP2FastCGIProxyServer.java @@ -43,8 +43,7 @@ public class WordPressHTTP2FastCGIProxyServer { int tlsPort = 8443; - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(""); + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); diff --git a/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-embedded.mod b/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-embedded.mod index 2263ae0807b..405b5209aaf 100644 --- a/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-embedded.mod +++ b/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-embedded.mod @@ -13,7 +13,7 @@ session-store sessions [files] -maven://com.hazelcast/hazelcast/3.8.2|lib/hazelcast/hazelcast-3.8.2.jar +maven://com.hazelcast/hazelcast/3.9.3|lib/hazelcast/hazelcast-3.9.3.jar [xml] etc/sessions/hazelcast/default.xml @@ -33,4 +33,4 @@ jetty.session.hazelcast.mapName=jetty-distributed-session-map jetty.session.hazelcast.hazelcastInstanceName=JETTY_DISTRIBUTED_SESSION_INSTANCE #jetty.session.hazelcast.configurationLocation= jetty.session.gracePeriod.seconds=3600 -jetty.session.savePeriod.seconds=0 \ No newline at end of file +jetty.session.savePeriod.seconds=0 diff --git a/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-remote.mod b/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-remote.mod index c6a26fc7123..29e3a253171 100644 --- a/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-remote.mod +++ b/jetty-hazelcast/src/main/config/modules/session-store-hazelcast-remote.mod @@ -13,8 +13,8 @@ session-store sessions [files] -maven://com.hazelcast/hazelcast/3.8.2|lib/hazelcast/hazelcast-3.8.2.jar -maven://com.hazelcast/hazelcast-client/3.8.2|lib/hazelcast/hazelcast-client-3.8.2.jar +maven://com.hazelcast/hazelcast/3.9.3|lib/hazelcast/hazelcast-3.9.3.jar +maven://com.hazelcast/hazelcast-client/3.9.3|lib/hazelcast/hazelcast-client-3.9.3.jar [xml] etc/sessions/hazelcast/remote.xml @@ -35,4 +35,4 @@ jetty.session.hazelcast.hazelcastInstanceName=JETTY_DISTRIBUTED_SESSION_INSTANCE jetty.session.hazelcast.onlyClient=true #jetty.session.hazelcast.configurationLocation= jetty.session.gracePeriod.seconds=3600 -jetty.session.savePeriod.seconds=0 \ No newline at end of file +jetty.session.savePeriod.seconds=0 diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index f9a8f95c0ba..1164d97cff5 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.StacklessLogging; import org.hamcrest.Matchers; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_INSENSITIVE_METHOD; @@ -1975,6 +1976,7 @@ public class HttpParserTest } @Test + @Tag("ipv6") public void testIPv6Host() throws Exception { ByteBuffer buffer = BufferUtil.toBuffer( @@ -2056,6 +2058,7 @@ public class HttpParserTest } @Test + @Tag("ipv6") public void testIPv6HostPort() throws Exception { ByteBuffer buffer = BufferUtil.toBuffer( diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java index b6cd168abe3..75790060d48 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/AbstractTest.java @@ -65,7 +65,7 @@ public class AbstractTest protected void prepareClient() throws Exception { - client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()), null); + client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client())); QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/DirectHTTP2OverTLSTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/DirectHTTP2OverTLSTest.java index 53e0f530f5c..bb34c209727 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/DirectHTTP2OverTLSTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/DirectHTTP2OverTLSTest.java @@ -18,10 +18,8 @@ package org.eclipse.jetty.http2.client.http; -import java.io.IOException; import java.util.concurrent.TimeUnit; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -32,6 +30,7 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http2.HTTP2Cipher; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; @@ -68,7 +67,7 @@ public class DirectHTTP2OverTLSTest HttpConfiguration httpsConfig = new HttpConfiguration(); httpsConfig.addCustomizer(new SecureRequestCustomizer()); ConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig); - ConnectionFactory ssl = new SslConnectionFactory(newSslContextFactory(), h2.getProtocol()); + ConnectionFactory ssl = new SslConnectionFactory(newServerSslContextFactory(), h2.getProtocol()); connector = new ServerConnector(server, 1, 1, ssl, h2); server.addConnector(connector); server.setHandler(handler); @@ -77,14 +76,14 @@ public class DirectHTTP2OverTLSTest private void startClient() throws Exception { + ClientConnector clientConnector = new ClientConnector(); QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - HttpClientTransportOverHTTP2 transport = new HttpClientTransportOverHTTP2(new HTTP2Client()); + clientConnector.setExecutor(clientThreads); + clientConnector.setSslContextFactory(newClientSslContextFactory()); + HttpClientTransportOverHTTP2 transport = new HttpClientTransportOverHTTP2(new HTTP2Client(clientConnector)); transport.setUseALPN(false); - SslContextFactory sslContextFactory = newSslContextFactory(); - sslContextFactory.setEndpointIdentificationAlgorithm(null); - client = new HttpClient(transport, sslContextFactory); - client.setExecutor(clientThreads); + client = new HttpClient(transport); client.start(); } @@ -97,14 +96,27 @@ public class DirectHTTP2OverTLSTest server.stop(); } - private SslContextFactory newSslContextFactory() + private SslContextFactory.Server newServerSslContextFactory() + { + SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); + configureSslContextFactory(sslContextFactory); + return sslContextFactory; + } + + private SslContextFactory.Client newClientSslContextFactory() + { + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + configureSslContextFactory(sslContextFactory); + sslContextFactory.setEndpointIdentificationAlgorithm(null); + return sslContextFactory; + } + + private void configureSslContextFactory(SslContextFactory sslContextFactory) { - SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setUseCipherSuitesOrder(true); sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR); - return sslContextFactory; } @Test @@ -115,7 +127,7 @@ public class DirectHTTP2OverTLSTest start(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); } 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 00b92695f73..34ee90517f8 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 @@ -18,16 +18,6 @@ package org.eclipse.jetty.http2.client.http; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; @@ -48,7 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -76,6 +65,7 @@ import org.eclipse.jetty.http2.generator.Generator; import org.eclipse.jetty.http2.parser.ServerParser; import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory; import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.Request; @@ -87,13 +77,22 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class HttpClientTransportOverHTTP2Test extends AbstractTest { @Test public void testPropertiesAreForwarded() throws Exception { HTTP2Client http2Client = new HTTP2Client(); - HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), null); + HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client)); Executor executor = new QueuedThreadPool(); httpClient.setExecutor(executor); httpClient.setConnectTimeout(13); @@ -133,11 +132,10 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest } }); - assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .onRequestCommit(request -> request.abort(new Exception("explicitly_aborted_by_test"))) - .send(); - }); + assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .onRequestCommit(request -> request.abort(new Exception("explicitly_aborted_by_test"))) + .send()); assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); } @@ -172,11 +170,10 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest } }); - assertThrows(ExecutionException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - .onResponseContent((response, buffer) -> response.abort(new Exception("explicitly_aborted_by_test"))) - .send(); - }); + assertThrows(ExecutionException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + .onResponseContent((response, buffer) -> response.abort(new Exception("explicitly_aborted_by_test"))) + .send()); assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); } @@ -186,7 +183,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest start(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); HttpVersion version = HttpVersion.fromString(request.getProtocol()); @@ -274,7 +271,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest lastStream.set(frame.getLastStreamId()); latch.countDown(); } - }, null); + }); QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); @@ -312,7 +309,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest start(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); assertEquals(path, request.getRequestURI()); @@ -336,7 +333,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest start(new AbstractHandler() { @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); assertEquals(path, request.getRequestURI()); @@ -381,12 +378,11 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest client.setIdleTimeout(idleTimeout); client.start(); - assertThrows(TimeoutException.class, ()->{ - client.newRequest("localhost", connector.getLocalPort()) - // Make sure the connection idle times out, not the stream. - .idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS) - .send(); - }); + assertThrows(TimeoutException.class, () -> + client.newRequest("localhost", connector.getLocalPort()) + // Make sure the connection idle times out, not the stream. + .idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS) + .send()); assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); } @@ -436,7 +432,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest sessions.add(session); return super.newHttpConnection(destination, session); } - }, null); + }); QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); @@ -600,12 +596,13 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest @Test public void testExternalServer() throws Exception { - HTTP2Client http2Client = new HTTP2Client(); - SslContextFactory sslContextFactory = new SslContextFactory(); - HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory); + ClientConnector clientConnector = new ClientConnector(); + HTTP2Client http2Client = new HTTP2Client(clientConnector); + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + clientConnector.setSslContextFactory(sslContextFactory); + HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client)); Executor executor = new QueuedThreadPool(); - httpClient.setExecutor(executor); - + clientConnector.setExecutor(executor); httpClient.start(); // ContentResponse response = httpClient.GET("https://http2.akamai.com/"); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java index 6ae87a5064f..4a0c29691c7 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/MaxConcurrentStreamsTest.java @@ -206,7 +206,7 @@ public class MaxConcurrentStreamsTest extends AbstractTest } }, promise, context); } - }, null); + }); QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnector.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnector.java index 29ce05f4564..afe22f23e55 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnector.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ClientConnector.java @@ -50,7 +50,7 @@ public class ClientConnector extends ContainerLifeCycle private Executor executor; private Scheduler scheduler; private ByteBufferPool byteBufferPool; - private SslContextFactory sslContextFactory; + private SslContextFactory.Client sslContextFactory; private SelectorManager selectorManager; private int selectors = 1; private boolean connectBlocking; @@ -97,12 +97,12 @@ public class ClientConnector extends ContainerLifeCycle this.byteBufferPool = byteBufferPool; } - public SslContextFactory getSslContextFactory() + public SslContextFactory.Client getSslContextFactory() { return sslContextFactory; } - public void setSslContextFactory(SslContextFactory sslContextFactory) + public void setSslContextFactory(SslContextFactory.Client sslContextFactory) { if (isStarted()) throw new IllegalStateException(); @@ -192,9 +192,9 @@ public class ClientConnector extends ContainerLifeCycle removeBean(selectorManager); } - protected SslContextFactory newSslContextFactory() + protected SslContextFactory.Client newSslContextFactory() { - SslContextFactory sslContextFactory = new SslContextFactory(false); + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(false); sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS"); return sslContextFactory; } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java index 4594b5a9299..88a604f1130 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java @@ -295,8 +295,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable } catch (Throwable x) { - if (LOG.isDebugEnabled()) - LOG.debug(x); + LOG.ignore(x); return -1; } } @@ -309,8 +308,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable } catch (Throwable x) { - if (LOG.isDebugEnabled()) - LOG.debug(x); + LOG.ignore(x); return -1; } } 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 0468f3a15ca..85173d9352e 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 @@ -389,9 +389,9 @@ abstract public class WriteFlusher boolean progress = true; while (progress && buffers != null) { - long before = remaining(buffers); + long before = BufferUtil.remaining(buffers); boolean flushed = _endPoint.flush(buffers); - long after = remaining(buffers); + long after = BufferUtil.remaining(buffers); long written = before - after; if (LOG.isDebugEnabled()) @@ -441,16 +441,6 @@ abstract public class WriteFlusher return buffers == null ? EMPTY_BUFFERS : buffers; } - private long remaining(ByteBuffer[] buffers) - { - if (buffers == null) - return 0; - long result = 0; - for (ByteBuffer buffer : buffers) - result += buffer.remaining(); - return result; - } - /** * Notify the flusher of a failure * diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java index 15518193881..3bfcf2e99f3 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java @@ -835,6 +835,12 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr LOG.debug("flush b[{}]={}", i++, BufferUtil.toDetailString(b)); } + // finish of any previous flushes + if (BufferUtil.hasContent(_encryptedOutput) && !getEndPoint().flush(_encryptedOutput)) + return false; + + boolean isEmpty = BufferUtil.isEmpty(appOuts); + Boolean result = null; try { @@ -866,7 +872,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr if (filled < 0) throw new IOException("Broken pipe"); } - return result = false; + return result = isEmpty; default: throw new IllegalStateException("Unexpected HandshakeStatus " + status); @@ -895,10 +901,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr _sslEngine.isOutboundDone()); // Was all the data consumed? - boolean allConsumed = true; - for (ByteBuffer b : appOuts) - if (BufferUtil.hasContent(b)) - allConsumed = false; + isEmpty = BufferUtil.isEmpty(appOuts); // if we have net bytes, let's try to flush them boolean flushed = true; @@ -906,7 +909,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr flushed = getEndPoint().flush(_encryptedOutput); if (LOG.isDebugEnabled()) - LOG.debug("net flushed={}, ac={}", flushed, allConsumed); + LOG.debug("net flushed={}, ac={}", flushed, isEmpty); // Now deal with the results returned from the wrap Status wrap = wrapResult.getStatus(); @@ -919,7 +922,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr if (!flushed) return result = false; getEndPoint().shutdownOutput(); - if (allConsumed) + if (isEmpty) return result = true; throw new IOException("Broken pipe"); } @@ -936,15 +939,20 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr if (isRenegotiating() && !allowRenegotiate()) { getEndPoint().shutdownOutput(); - if (allConsumed && BufferUtil.isEmpty(_encryptedOutput)) + if (isEmpty && BufferUtil.isEmpty(_encryptedOutput)) return result = true; throw new IOException("Broken pipe"); } if (!flushed) return result = false; - if (allConsumed) - return result = true; + + if (isEmpty) + { + if (wrapResult.getHandshakeStatus() != HandshakeStatus.NEED_WRAP || + wrapResult.bytesProduced() == 0) + return result = true; + } break; default: @@ -1073,14 +1081,15 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr @Override public void doShutdownOutput() { + final EndPoint endp = getEndPoint(); try { boolean close; boolean flush = false; synchronized (_decryptedEndPoint) { - boolean ishut = getEndPoint().isInputShutdown(); - boolean oshut = getEndPoint().isOutputShutdown(); + boolean ishut = endp.isInputShutdown(); + boolean oshut = endp.isOutputShutdown(); if (LOG.isDebugEnabled()) LOG.debug("shutdownOutput: {} oshut={}, ishut={} {}", SslConnection.this, oshut, ishut); @@ -1097,16 +1106,28 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr } if (flush) - flush(BufferUtil.EMPTY_BUFFER); // Send the TLS close message. + { + if (!flush(BufferUtil.EMPTY_BUFFER) && !close) + { + Thread.yield(); + // if we still can't flush, but we are not closing the endpoint, + // let's just flush the encrypted output in the background. + // and continue as if we are closed. The assumption here is that + // the encrypted buffer will contain the entire close handshake + // and that a call to flush(EMPTY_BUFFER) is not needed. + endp.write(Callback.from(() -> {}, t -> endp.close()), _encryptedOutput); + } + } + if (close) - getEndPoint().close(); + endp.close(); else ensureFillInterested(); } catch (Throwable x) { LOG.ignore(x); - getEndPoint().close(); + endp.close(); } } diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SocketChannelEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SocketChannelEndPointTest.java index 96230e2c675..a2292d3a298 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/SocketChannelEndPointTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SocketChannelEndPointTest.java @@ -625,24 +625,23 @@ public class SocketChannelEndPointTest public static class SslScenario implements Scenario { private final NormalScenario _normalScenario; - private final SslContextFactory __sslCtxFactory = new SslContextFactory(); - private final ByteBufferPool __byteBufferPool = new MappedByteBufferPool(); + private final SslContextFactory _sslCtxFactory = new SslContextFactory.Server(); + private final ByteBufferPool _byteBufferPool = new MappedByteBufferPool(); public SslScenario(NormalScenario normalScenario) throws Exception { _normalScenario = normalScenario; File keystore = MavenTestingUtils.getTestResourceFile("keystore"); - __sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); - __sslCtxFactory.setKeyStorePassword("storepwd"); - __sslCtxFactory.setKeyManagerPassword("keypwd"); - __sslCtxFactory.setEndpointIdentificationAlgorithm(""); - __sslCtxFactory.start(); + _sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); + _sslCtxFactory.setKeyStorePassword("storepwd"); + _sslCtxFactory.setKeyManagerPassword("keypwd"); + _sslCtxFactory.start(); } @Override public Socket newClient(ServerSocketChannel connector) throws IOException { - SSLSocket socket = __sslCtxFactory.newSslSocket(); + SSLSocket socket = _sslCtxFactory.newSslSocket(); socket.connect(connector.socket().getLocalSocketAddress()); return socket; } @@ -650,11 +649,11 @@ public class SocketChannelEndPointTest @Override public Connection newConnection(SelectableChannel channel, EndPoint endpoint, Executor executor, AtomicInteger blockAt, AtomicInteger writeCount) { - SSLEngine engine = __sslCtxFactory.newSSLEngine(); + SSLEngine engine = _sslCtxFactory.newSSLEngine(); engine.setUseClientMode(false); - SslConnection sslConnection = new SslConnection(__byteBufferPool, executor, endpoint, engine); - sslConnection.setRenegotiationAllowed(__sslCtxFactory.isRenegotiationAllowed()); - sslConnection.setRenegotiationLimit(__sslCtxFactory.getRenegotiationLimit()); + SslConnection sslConnection = new SslConnection(_byteBufferPool, executor, endpoint, engine); + sslConnection.setRenegotiationAllowed(_sslCtxFactory.isRenegotiationAllowed()); + sslConnection.setRenegotiationLimit(_sslCtxFactory.getRenegotiationLimit()); Connection appConnection = _normalScenario.newConnection(channel, sslConnection.getDecryptedEndPoint(), executor, blockAt, writeCount); sslConnection.getDecryptedEndPoint().setConnection(appConnection); return sslConnection; diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java index dfbb26e0f0f..70634cac55a 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; +import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -31,6 +32,7 @@ import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.SSLEngine; @@ -50,6 +52,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -60,9 +64,11 @@ public class SslConnectionTest private static final int TIMEOUT = 1000000; private static ByteBufferPool __byteBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); - private final SslContextFactory _sslCtxFactory =new SslContextFactory(); + private final SslContextFactory _sslCtxFactory = new SslContextFactory.Server(); protected volatile EndPoint _lastEndp; private volatile boolean _testFill=true; + private volatile boolean _onXWriteThenShutdown=false; + private volatile FutureCallback _writeCallback; protected ServerSocketChannel _connector; final AtomicInteger _dispatches = new AtomicInteger(); @@ -92,7 +98,6 @@ public class SslConnectionTest return sslConnection; } - @Override protected EndPoint newEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey selectionKey) { @@ -105,6 +110,7 @@ public class SslConnectionTest static final AtomicInteger __startBlocking = new AtomicInteger(); static final AtomicInteger __blockFor = new AtomicInteger(); + static final AtomicBoolean __onIncompleteFlush = new AtomicBoolean(); private static class TestEP extends SocketChannelEndPoint { public TestEP(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler) @@ -115,13 +121,14 @@ public class SslConnectionTest @Override protected void onIncompleteFlush() { - super.onIncompleteFlush(); + __onIncompleteFlush.set(true); } @Override public boolean flush(ByteBuffer... buffers) throws IOException { + __onIncompleteFlush.set(false); if (__startBlocking.get()==0 || __startBlocking.decrementAndGet()==0) { if (__blockFor.get()>0 && __blockFor.getAndDecrement()>0) @@ -133,7 +140,6 @@ public class SslConnectionTest } } - @BeforeEach public void initSSL() throws Exception { @@ -143,7 +149,6 @@ public class SslConnectionTest _sslCtxFactory.setKeyManagerPassword("keypwd"); _sslCtxFactory.setRenegotiationAllowed(true); _sslCtxFactory.setRenegotiationLimit(-1); - _sslCtxFactory.setEndpointIdentificationAlgorithm(null); startManager(); } @@ -227,20 +232,23 @@ public class SslConnectionTest filled=endp.fill(_in); } + boolean shutdown = _onXWriteThenShutdown && BufferUtil.toString(_in).contains("X"); + // Write everything int l=_in.remaining(); if (l>0) { FutureCallback blockingWrite= new FutureCallback(); + endp.write(blockingWrite,_in); blockingWrite.get(); + if (shutdown) + endp.shutdownOutput(); } // are we done? - if (endp.isInputShutdown()) - { + if (endp.isInputShutdown() || shutdown) endp.shutdownOutput(); - } } } catch(InterruptedException|EofException e) @@ -426,7 +434,7 @@ public class SslConnectionTest public void testBlockedWrite() throws Exception { startSSL(); - try (Socket client = newClient()) + try (SSLSocket client = newClient()) { client.setSoTimeout(5000); try (SocketChannel server = _connector.accept()) @@ -434,21 +442,78 @@ public class SslConnectionTest server.configureBlocking(false); _manager.accept(server); - __startBlocking.set(5); - __blockFor.set(3); - client.getOutputStream().write("Hello".getBytes(StandardCharsets.UTF_8)); byte[] buffer = new byte[1024]; int len = client.getInputStream().read(buffer); - assertEquals(5, len); assertEquals("Hello", new String(buffer, 0, len, StandardCharsets.UTF_8)); + __startBlocking.set(0); + __blockFor.set(2); _dispatches.set(0); client.getOutputStream().write("World".getBytes(StandardCharsets.UTF_8)); - len = 5; - while (len > 0) - len -= client.getInputStream().read(buffer); - assertEquals(0, len); + + try + { + client.setSoTimeout(500); + client.getInputStream().read(buffer); + throw new IllegalStateException(); + } + catch(SocketTimeoutException e) + { + } + + + assertTrue(__onIncompleteFlush.get()); + ((TestEP)_lastEndp).getWriteFlusher().completeWrite(); + + len = client.getInputStream().read(buffer); + assertEquals("World", new String(buffer, 0, len, StandardCharsets.UTF_8)); + } + } + } + + @Test + public void testBlockedClose() throws Exception + { + startSSL(); + try (SSLSocket client = newClient()) + { + client.setSoTimeout(5000); + try (SocketChannel server = _connector.accept()) + { + server.configureBlocking(false); + _manager.accept(server); + + //__startBlocking.set(5); + //__blockFor.set(3); + + client.getOutputStream().write("Short".getBytes(StandardCharsets.UTF_8)); + byte[] buffer = new byte[1024]; + int len = client.getInputStream().read(buffer); + assertEquals("Short", new String(buffer, 0, len, StandardCharsets.UTF_8)); + + _onXWriteThenShutdown=true; + __startBlocking.set(2); // block on the close handshake flush + __blockFor.set(Integer.MAX_VALUE); // > retry loops in SslConnection + 1 + client.getOutputStream().write("This is a much longer example with X".getBytes(StandardCharsets.UTF_8)); + len = client.getInputStream().read(buffer); + assertEquals("This is a much longer example with X", new String(buffer, 0, len, StandardCharsets.UTF_8)); + + try + { + client.setSoTimeout(500); + client.getInputStream().read(buffer); + throw new IllegalStateException(); + } + catch(SocketTimeoutException e) + { + } + + __blockFor.set(0); + assertTrue(__onIncompleteFlush.get()); + ((TestEP)_lastEndp).getWriteFlusher().completeWrite(); + len = client.getInputStream().read(buffer); + assertThat(len, is(len)); } } } @@ -478,7 +543,6 @@ public class SslConnectionTest String line = in.readLine(); if (line == null) break; - // System.err.println(line); count.countDown(); } } @@ -491,7 +555,6 @@ public class SslConnectionTest for (int i = 0; i < LINES; i++) { client.getOutputStream().write(("HelloWorld " + i + "\n").getBytes(StandardCharsets.UTF_8)); - // System.err.println("wrote"); if (i % 1000 == 0) { client.getOutputStream().flush(); diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SslEngineBehaviorTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SslEngineBehaviorTest.java index ac6a8ac1d3a..d8bee115735 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/SslEngineBehaviorTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SslEngineBehaviorTest.java @@ -18,10 +18,6 @@ package org.eclipse.jetty.io; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.hamcrest.MatcherAssert.assertThat; - import java.io.File; import java.nio.ByteBuffer; @@ -32,12 +28,15 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.AfterAll; - import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnJre; import org.junit.jupiter.api.condition.JRE; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class SslEngineBehaviorTest { private static SslContextFactory sslCtxFactory; @@ -45,12 +44,11 @@ public class SslEngineBehaviorTest @BeforeAll public static void startSsl() throws Exception { - sslCtxFactory = new SslContextFactory(); + sslCtxFactory = new SslContextFactory.Server(); File keystore = MavenTestingUtils.getTestResourceFile("keystore"); sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); sslCtxFactory.setKeyStorePassword("storepwd"); sslCtxFactory.setKeyManagerPassword("keypwd"); - sslCtxFactory.setEndpointIdentificationAlgorithm(""); sslCtxFactory.start(); } diff --git a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ConnectorServerTest.java b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ConnectorServerTest.java index 0fd9ad74dd1..661f34f696b 100644 --- a/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ConnectorServerTest.java +++ b/jetty-jmx/src/test/java/org/eclipse/jetty/jmx/ConnectorServerTest.java @@ -18,10 +18,6 @@ package org.eclipse.jetty.jmx; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.net.ConnectException; import java.net.InetAddress; import java.net.ServerSocket; @@ -40,6 +36,10 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * Running the tests of this class in the same JVM results often in *
@@ -227,7 +227,7 @@ public class ConnectorServerTest
     @Test
     public void testJMXOverTLS() throws Exception
     {
-        SslContextFactory sslContextFactory = new SslContextFactory();
+        SslContextFactory sslContextFactory = new SslContextFactory.Server();
         String keyStorePath = MavenTestingUtils.getTestResourcePath("keystore.jks").toString();
         String keyStorePassword = "storepwd";
         sslContextFactory.setKeyStorePath(keyStorePath);
diff --git a/jetty-memcached/jetty-memcached-sessions/pom.xml b/jetty-memcached/jetty-memcached-sessions/pom.xml
index 1635ddf8177..1b889901d19 100644
--- a/jetty-memcached/jetty-memcached-sessions/pom.xml
+++ b/jetty-memcached/jetty-memcached-sessions/pom.xml
@@ -24,7 +24,7 @@
     
       org.slf4j
       slf4j-simple
-      1.7.9
+      ${slf4j.version}
       test
     
     
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-ssl.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-ssl.xml
index 117e8626733..86f7221a643 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-ssl.xml
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-ssl.xml
@@ -29,7 +29,7 @@
   
   
   
-  
+  
     
     /
     
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2Conscrypt.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2Conscrypt.java
index 0c37ae5856d..9099331f971 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2Conscrypt.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2Conscrypt.java
@@ -30,6 +30,7 @@ import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.http2.client.HTTP2Client;
 import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.eclipse.jetty.io.ClientConnector;
 import org.eclipse.jetty.util.JavaVersion;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -137,8 +138,8 @@ public class TestJettyOSGiBootHTTP2Conscrypt
             Path path = Paths.get("src", "test", "config");
             File keys = path.resolve("etc").resolve("keystore").toFile();
 
-            HTTP2Client http2Client = new HTTP2Client();
-            SslContextFactory sslContextFactory = new SslContextFactory();
+            ClientConnector clientConnector = new ClientConnector();
+            SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
             sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
             sslContextFactory.setTrustStorePath(keys.getAbsolutePath());
             sslContextFactory.setKeyStorePath(keys.getAbsolutePath());
@@ -150,7 +151,9 @@ public class TestJettyOSGiBootHTTP2Conscrypt
                 // Conscrypt enables TLSv1.3 by default but it's not supported in Java 8.
                 sslContextFactory.addExcludeProtocols("TLSv1.3");
             }
-            HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory);
+            clientConnector.setSslContextFactory(sslContextFactory);
+            HTTP2Client http2Client = new HTTP2Client(clientConnector);
+            HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client));
             Executor executor = new QueuedThreadPool();
             httpClient.setExecutor(executor);
 
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2JDK9.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2JDK9.java
index 728bb12578c..856b2a5b900 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2JDK9.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootHTTP2JDK9.java
@@ -31,6 +31,7 @@ import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.http2.client.HTTP2Client;
 import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
+import org.eclipse.jetty.io.ClientConnector;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
 import org.junit.Test;
@@ -131,15 +132,16 @@ public class TestJettyOSGiBootHTTP2JDK9
             Path path = Paths.get("src", "test", "config");
             File keys = path.resolve("etc").resolve("keystore").toFile();
             
-            //set up client to do http2
-            http2Client = new HTTP2Client();
-            SslContextFactory sslContextFactory = new SslContextFactory();
+            ClientConnector clientConnector = new ClientConnector();
+            SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
             sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
             sslContextFactory.setTrustStorePath(keys.getAbsolutePath());
             sslContextFactory.setKeyStorePath(keys.getAbsolutePath());
             sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
             sslContextFactory.setEndpointIdentificationAlgorithm(null);
-            httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory);
+            clientConnector.setSslContextFactory(sslContextFactory);
+            http2Client = new HTTP2Client(clientConnector);
+            httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client));
             Executor executor = new QueuedThreadPool();
             httpClient.setExecutor(executor);
             httpClient.start();
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
index 1f472423580..44ece33ce84 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestOSGiUtil.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -31,7 +32,9 @@ import javax.servlet.http.HttpServletResponse;
 
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
 import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.io.ClientConnector;
 import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
 import org.eclipse.jetty.toolchain.test.FS;
 import org.eclipse.jetty.util.StringUtil;
@@ -56,7 +59,6 @@ import static org.ops4j.pax.exam.CoreOptions.systemProperty;
  */
 public class TestOSGiUtil
 {
-    
     public static final String BUNDLE_DEBUG = "bundle.debug";
 
     public static List