Merge remote-tracking branch 'eclipse/jetty-10.0.x' into jetty-10.0.x-3494-clientclosetest

Signed-off-by: lachan-roberts <lachlan@webtide.com>
This commit is contained in:
lachan-roberts 2019-04-09 18:18:50 +10:00
commit 002ecf526d
159 changed files with 3053 additions and 1662 deletions

2
Jenkinsfile vendored
View File

@ -97,7 +97,7 @@ def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) {
mavenOpts: mavenOpts, mavenOpts: mavenOpts,
mavenLocalRepo: localRepo) { mavenLocalRepo: localRepo) {
// Some common Maven command line + provided command line // 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
} }
} }

View File

@ -25,7 +25,6 @@ import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode; import java.nio.channels.FileChannel.MapMode;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -116,7 +115,8 @@ public class FastFileServer
} }
String listing = Resource.newResource(file).getListHTML( String listing = Resource.newResource(file).getListHTML(
request.getRequestURI(), request.getRequestURI(),
request.getPathInfo().lastIndexOf("/") > 0); request.getPathInfo().lastIndexOf("/") > 0,
request.getQueryString());
response.setContentType("text/html; charset=utf-8"); response.setContentType("text/html; charset=utf-8");
response.getWriter().println(listing); response.getWriter().println(listing);
return; return;

View File

@ -60,10 +60,6 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.PushCacheFilter; import org.eclipse.jetty.servlets.PushCacheFilter;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
/* ------------------------------------------------------------ */
/**
*/
public class Http2Server public class Http2Server
{ {
public static void main(String... args) throws Exception 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"); String jetty_distro = System.getProperty("jetty.distro","../../jetty-distribution/target/distribution");
if (!new File(jetty_distro).exists()) if (!new File(jetty_distro).exists())
jetty_distro = "jetty-distribution/target/distribution"; 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.setKeyStorePath(jetty_distro + "/demo-base/etc/keystore");
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -139,7 +139,7 @@ public class LikeJettyXml
// === jetty-https.xml === // === jetty-https.xml ===
// SSL Context Factory // 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.setKeyStorePath(jetty_home + "/../../../jetty-server/src/test/config/etc/keystore");
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -20,9 +20,7 @@ package org.eclipse.jetty.embedded;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.security.Security;
import org.conscrypt.OpenSSLProvider;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
@ -89,7 +87,7 @@ public class ManyConnectors
// including things like choosing the particular certificate out of a // including things like choosing the particular certificate out of a
// keystore to be used. // keystore to be used.
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath()); sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath());
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -32,6 +32,7 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
@ -60,24 +61,35 @@ public class ConscryptHTTP2ServerTest
private Server server = new Server(); 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"); Path path = Paths.get("src", "test", "resources");
File keys = path.resolve("keystore").toFile(); File keys = path.resolve("keystore").toFile();
sslContextFactory.setKeyStorePath(keys.getAbsolutePath());
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setTrustStorePath(keys.getAbsolutePath()); sslContextFactory.setTrustStorePath(keys.getAbsolutePath());
sslContextFactory.setKeyStorePath(keys.getAbsolutePath());
sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setProvider("Conscrypt"); sslContextFactory.setProvider("Conscrypt");
sslContextFactory.setEndpointIdentificationAlgorithm(null);
if (JavaVersion.VERSION.getPlatform() < 9) if (JavaVersion.VERSION.getPlatform() < 9)
{ {
// Conscrypt enables TLSv1.3 by default but it's not supported in Java 8. // Conscrypt enables TLSv1.3 by default but it's not supported in Java 8.
sslContextFactory.addExcludeProtocols("TLSv1.3"); sslContextFactory.addExcludeProtocols("TLSv1.3");
} }
return sslContextFactory;
} }
@BeforeEach @BeforeEach
@ -94,7 +106,7 @@ public class ConscryptHTTP2ServerTest
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig); HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(http.getProtocol()); 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); ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, h2, http);
http2Connector.setPort(0); http2Connector.setPort(0);
@ -123,8 +135,10 @@ public class ConscryptHTTP2ServerTest
@Test @Test
public void testSimpleRequest() throws Exception public void testSimpleRequest() throws Exception
{ {
HTTP2Client h2Client = new HTTP2Client(); ClientConnector clientConnector = new ClientConnector();
HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client), newSslContextFactory()); clientConnector.setSslContextFactory(newClientSslContextFactory());
HTTP2Client h2Client = new HTTP2Client(clientConnector);
HttpClient client = new HttpClient(new HttpClientTransportOverHTTP2(h2Client));
client.start(); client.start();
try try
{ {

View File

@ -59,7 +59,7 @@ public class JDK9ALPNTest
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpConfiguration); HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpConfiguration);
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory(); ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
alpn.setDefaultProtocol(h1.getProtocol()); alpn.setDefaultProtocol(h1.getProtocol());
connector = new ServerConnector(server, newSslContextFactory(), alpn, h1, h2); connector = new ServerConnector(server, newServerSslContextFactory(), alpn, h1, h2);
server.addConnector(connector); server.addConnector(connector);
server.setHandler(handler); server.setHandler(handler);
server.start(); server.start();
@ -72,9 +72,9 @@ public class JDK9ALPNTest
server.stop(); 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.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
@ -95,7 +95,7 @@ public class JDK9ALPNTest
} }
}); });
SslContextFactory sslContextFactory = new SslContextFactory(true); SslContextFactory sslContextFactory = new SslContextFactory.Client(true);
sslContextFactory.start(); sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext(); SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort())) 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(); sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext(); SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort())) try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort()))

View File

@ -45,7 +45,7 @@ public class JDK9HTTP2Server
httpsConfig.setSendServerVersion(true); httpsConfig.setSendServerVersion(true);
httpsConfig.addCustomizer(new SecureRequestCustomizer()); httpsConfig.addCustomizer(new SecureRequestCustomizer());
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g"); sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -217,6 +218,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
path = request.getPath(); path = request.getPath();
} }
Request newRequest = client.copyRequest(request, requestURI); 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) if (path != null)
newRequest.path(path); newRequest.path(path);

View File

@ -159,47 +159,11 @@ public class HttpClient extends ContainerLifeCycle
this(new HttpClientTransportOverHTTP()); 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) 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); this.transport = Objects.requireNonNull(transport);
addBean(transport); addBean(transport);
this.connector = ((AbstractHttpClientTransport)transport).getBean(ClientConnector.class); this.connector = ((AbstractHttpClientTransport)transport).getBean(ClientConnector.class);
if (sslContextFactory != null)
connector.setSslContextFactory(sslContextFactory);
addBean(handlers); addBean(handlers);
addBean(decoderFactories); addBean(decoderFactories);
} }
@ -217,9 +181,8 @@ public class HttpClient extends ContainerLifeCycle
/** /**
* @return the {@link SslContextFactory} that manages TLS encryption * @return the {@link SslContextFactory} that manages TLS encryption
* @see #HttpClient(SslContextFactory)
*/ */
public SslContextFactory getSslContextFactory() public SslContextFactory.Client getSslContextFactory()
{ {
return connector.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) * @see #setMaxRedirects(int)
*/ */
public int getMaxRedirects() 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) * @see #setFollowRedirects(boolean)
*/ */
public void setMaxRedirects(int maxRedirects) public void setMaxRedirects(int maxRedirects)

View File

@ -25,9 +25,13 @@ import java.util.concurrent.ConcurrentLinkedDeque;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.util.AttributesMap; 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 public class HttpConversation extends AttributesMap
{ {
private static final Logger LOG = Log.getLogger(HttpConversation.class);
private final Deque<HttpExchange> exchanges = new ConcurrentLinkedDeque<>(); private final Deque<HttpExchange> exchanges = new ConcurrentLinkedDeque<>();
private volatile List<Response.ResponseListener> listeners; private volatile List<Response.ResponseListener> listeners;
@ -118,6 +122,7 @@ public class HttpConversation extends AttributesMap
HttpExchange lastExchange = exchanges.peekLast(); HttpExchange lastExchange = exchanges.peekLast();
if (firstExchange == lastExchange) if (firstExchange == lastExchange)
{ {
// We don't have a conversation, just a single request.
if (overrideListener != null) if (overrideListener != null)
listeners.add(overrideListener); listeners.add(overrideListener);
else else
@ -125,13 +130,16 @@ public class HttpConversation extends AttributesMap
} }
else 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()); listeners.addAll(lastExchange.getResponseListeners());
if (overrideListener != null) if (overrideListener != null)
listeners.add(overrideListener); listeners.add(overrideListener);
else else
listeners.addAll(firstExchange.getResponseListeners()); listeners.addAll(firstExchange.getResponseListeners());
} }
if (LOG.isDebugEnabled())
LOG.debug("Exchanges in conversation {}, override={}, listeners={}", exchanges.size(), overrideListener, listeners);
this.listeners = listeners; this.listeners = listeners;
} }

View File

@ -72,12 +72,6 @@ public class HttpDestination extends ContainerLifeCycle implements Destination,
private final TimeoutTask timeout; private final TimeoutTask timeout;
private ConnectionPool connectionPool; private ConnectionPool connectionPool;
@Deprecated
public HttpDestination(HttpClient client, Origin origin)
{
this(client, new Key(origin, null));
}
public HttpDestination(HttpClient client, Key key) public HttpDestination(HttpClient client, Key key)
{ {
this(client, key, Function.identity()); 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 class TimeoutTask extends CyclicTimeout
{ {
private final AtomicLong nextTimeout = new AtomicLong(Long.MAX_VALUE); private final AtomicLong nextTimeout = new AtomicLong(Long.MAX_VALUE);
@ -696,6 +694,9 @@ public class HttpDestination extends ContainerLifeCycle implements Destination,
@Override @Override
public void onTimeoutExpired() public void onTimeoutExpired()
{ {
if (LOG.isDebugEnabled())
LOG.debug("{} timeout expired", this);
nextTimeout.set(Long.MAX_VALUE); nextTimeout.set(Long.MAX_VALUE);
long now = System.nanoTime(); long now = System.nanoTime();
long nextExpiresAt = Long.MAX_VALUE; long nextExpiresAt = Long.MAX_VALUE;
@ -728,12 +729,16 @@ public class HttpDestination extends ContainerLifeCycle implements Destination,
if (timeoutAt != expiresAt) if (timeoutAt != expiresAt)
{ {
long delay = expiresAt - System.nanoTime(); long delay = expiresAt - System.nanoTime();
if (LOG.isDebugEnabled())
LOG.debug("Scheduled timeout in {} ms", TimeUnit.NANOSECONDS.toMillis(delay));
if (delay <= 0) if (delay <= 0)
{
onTimeoutExpired(); onTimeoutExpired();
}
else else
{
schedule(delay, TimeUnit.NANOSECONDS); schedule(delay, TimeUnit.NANOSECONDS);
if (LOG.isDebugEnabled())
LOG.debug("{} scheduled timeout in {} ms", this, TimeUnit.NANOSECONDS.toMillis(delay));
}
} }
} }
} }

View File

@ -23,6 +23,7 @@ import java.net.URISyntaxException;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -61,10 +62,10 @@ public class HttpRedirector
{ {
private static final Logger LOG = Log.getLogger(HttpRedirector.class); private static final Logger LOG = Log.getLogger(HttpRedirector.class);
private static final String SCHEME_REGEXP = "(^https?)"; 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 // 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 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 QUERY_REGEXP = "([^#]*)";
private static final String FRAGMENT_REGEXP = "(.*)"; private static final String FRAGMENT_REGEXP = "(.*)";
private static final Pattern URI_PATTERN = Pattern.compile(DESTINATION_REGEXP + PATH_REGEXP + QUERY_REGEXP + 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. * 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 * @param response the response to the original request
* @return a {@link Result} object containing the request to the redirected location and its response * @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 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) * @see #redirect(Request, Response, Response.CompleteListener)
*/ */
public Result redirect(Request request, Response response) throws InterruptedException, ExecutionException public Result redirect(Request request, Response response) throws InterruptedException, ExecutionException
@ -144,7 +145,7 @@ public class HttpRedirector
/** /**
* Redirects the given {@code response} asynchronously. * 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 response the response to the original request
* @param listener the listener that receives response events * @param listener the listener that receives response events
* @return the request to the redirected location * @return the request to the redirected location
@ -292,7 +293,8 @@ public class HttpRedirector
Integer redirects = (Integer)conversation.getAttribute(ATTRIBUTE); Integer redirects = (Integer)conversation.getAttribute(ATTRIBUTE);
if (redirects == null) if (redirects == null)
redirects = 0; redirects = 0;
if (redirects < client.getMaxRedirects()) int maxRedirects = client.getMaxRedirects();
if (maxRedirects < 0 || redirects < maxRedirects)
{ {
++redirects; ++redirects;
conversation.setAttribute(ATTRIBUTE, redirects); conversation.setAttribute(ATTRIBUTE, redirects);
@ -310,19 +312,17 @@ public class HttpRedirector
try try
{ {
Request redirect = client.copyRequest(httpRequest, location); 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 // Use given method
redirect.method(method); redirect.method(method);
redirect.onRequestBegin(new Request.BeginListener() redirect.onRequestBegin(request ->
{ {
@Override Throwable cause = httpRequest.getAbortCause();
public void onBegin(Request redirect) if (cause != null)
{ request.abort(cause);
Throwable cause = httpRequest.getAbortCause();
if (cause != null)
redirect.abort(cause);
}
}); });
redirect.send(listener); redirect.send(listener);

View File

@ -26,7 +26,6 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.io.CyclicTimeout; 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.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler; 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); Request request = this.request.getAndSet(null);
if (LOG.isDebugEnabled()) 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) if (request != null)
request.abort(new TimeoutException("Total timeout " + request.getTimeout() + " ms elapsed")); 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(); boolean cancelled = cancel();
if (LOG.isDebugEnabled()) 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)) if (this.request.compareAndSet(null, request))
{ {
long delay = timeoutAt - System.nanoTime(); long delay = timeoutAt - System.nanoTime();
if (LOG.isDebugEnabled())
LOG.debug("Scheduled timeout in {} ms for {}", TimeUnit.NANOSECONDS.toMillis(delay), request);
if (delay <= 0) if (delay <= 0)
{
onTimeoutExpired(); onTimeoutExpired();
}
else else
{
schedule(delay, TimeUnit.NANOSECONDS); schedule(delay, TimeUnit.NANOSECONDS);
if (LOG.isDebugEnabled())
LOG.debug("Scheduled timeout in {} ms for {} on {}", TimeUnit.NANOSECONDS.toMillis(delay), request, this);
}
} }
} }
} }

View File

@ -261,12 +261,14 @@ public interface Request
Request idleTimeout(long timeout, TimeUnit unit); 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(); 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 * @param unit the timeout unit
* @return this request object * @return this request object
*/ */

View File

@ -24,6 +24,7 @@ import java.util.stream.Stream;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
@ -58,7 +59,7 @@ public abstract class AbstractHttpClientServerTest
serverThreads.setName("server"); serverThreads.setName("server");
server = new Server(serverThreads); server = new Server(serverThreads);
} }
connector = new ServerConnector(server, scenario.newSslContextFactory()); connector = new ServerConnector(server, scenario.newServerSslContextFactory());
connector.setPort(0); connector.setPort(0);
server.addConnector(connector); server.addConnector(connector);
server.setHandler(handler); server.setHandler(handler);
@ -67,30 +68,30 @@ public abstract class AbstractHttpClientServerTest
protected void startClient(final Scenario scenario) throws Exception protected void startClient(final Scenario scenario) throws Exception
{ {
startClient(scenario, null,null); startClient(scenario, null);
} }
protected void startClient(final Scenario scenario, HttpClientTransport transport, Consumer<HttpClient> config) throws Exception protected void startClient(final Scenario scenario, Consumer<HttpClient> config) throws Exception
{ {
if (transport==null) ClientConnector clientConnector = new ClientConnector();
transport = new HttpClientTransportOverHTTP(1); clientConnector.setSelectors(1);
clientConnector.setSslContextFactory(scenario.newClientSslContextFactory());
HttpClientTransport transport = new HttpClientTransportOverHTTP(clientConnector);
QueuedThreadPool executor = new QueuedThreadPool(); QueuedThreadPool executor = new QueuedThreadPool();
executor.setName("client"); executor.setName("client");
clientConnector.setExecutor(executor);
Scheduler scheduler = new ScheduledExecutorScheduler("client-scheduler", false); Scheduler scheduler = new ScheduledExecutorScheduler("client-scheduler", false);
client = newHttpClient(scenario, transport); clientConnector.setScheduler(scheduler);
client.setExecutor(executor); client = newHttpClient(transport);
client.setScheduler(scheduler);
client.setSocketAddressResolver(new SocketAddressResolver.Sync()); client.setSocketAddressResolver(new SocketAddressResolver.Sync());
if (config!=null) if (config != null)
config.accept(client); config.accept(client);
client.start(); 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 @AfterEach
@ -113,9 +114,10 @@ public abstract class AbstractHttpClientServerTest
} }
} }
public static class ScenarioProvider implements ArgumentsProvider { public static class ScenarioProvider implements ArgumentsProvider
{
@Override @Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception public Stream<? extends Arguments> provideArguments(ExtensionContext context)
{ {
return Stream.of( return Stream.of(
new NormalScenario(), new NormalScenario(),
@ -125,9 +127,10 @@ public abstract class AbstractHttpClientServerTest
} }
} }
public static class NonSslScenarioProvider implements ArgumentsProvider { public static class NonSslScenarioProvider implements ArgumentsProvider
{
@Override @Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception public Stream<? extends Arguments> provideArguments(ExtensionContext context)
{ {
return Stream.of( return Stream.of(
new NormalScenario() new NormalScenario()
@ -138,12 +141,27 @@ public abstract class AbstractHttpClientServerTest
public interface Scenario public interface Scenario
{ {
default SslContextFactory newSslContextFactory() { return null; } SslContextFactory.Client newClientSslContextFactory();
SslContextFactory.Server newServerSslContextFactory();
String getScheme(); String getScheme();
} }
public static class NormalScenario implements Scenario public static class NormalScenario implements Scenario
{ {
@Override
public SslContextFactory.Client newClientSslContextFactory()
{
return null;
}
@Override
public SslContextFactory.Server newServerSslContextFactory()
{
return null;
}
@Override @Override
public String getScheme() public String getScheme()
{ {
@ -160,15 +178,27 @@ public abstract class AbstractHttpClientServerTest
public static class SslScenario implements Scenario public static class SslScenario implements Scenario
{ {
@Override @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"); Path keystorePath = MavenTestingUtils.getTestResourcePath("keystore.jks");
SslContextFactory ssl = new SslContextFactory();
ssl.setEndpointIdentificationAlgorithm("");
ssl.setKeyStorePath(keystorePath.toString()); ssl.setKeyStorePath(keystorePath.toString());
ssl.setKeyStorePassword("storepwd"); ssl.setKeyStorePassword("storepwd");
return ssl;
} }
@Override @Override

View File

@ -18,9 +18,6 @@
package org.eclipse.jetty.client; 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.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -31,7 +28,6 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.Arguments;
import org.junit.jupiter.params.provider.MethodSource; 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 @Disabled // Disabled by @gregw on issue #2540 - commit 621b946b10884e7308eacca241dcf8b5d6f6cff2
public class ConnectionPoolTest public class ConnectionPoolTest
{ {
@ -83,7 +82,7 @@ public class ConnectionPoolTest
transport.setConnectionPoolFactory(factory); transport.setConnectionPoolFactory(factory);
server.start(); server.start();
client = new HttpClient(transport, null); client = new HttpClient(transport);
client.start(); client.start();
} }
@ -115,7 +114,7 @@ public class ConnectionPoolTest
start(factory, new EmptyServerHandler() start(factory, new EmptyServerHandler()
{ {
@Override @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())) switch (HttpMethod.fromString(request.getMethod()))
{ {

View File

@ -18,10 +18,6 @@
package org.eclipse.jetty.client; 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.net.Socket;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; 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.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; 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 @Disabled
public class ExternalSiteTest public class ExternalSiteTest
{ {
@ -44,7 +43,7 @@ public class ExternalSiteTest
@BeforeEach @BeforeEach
public void prepare() throws Exception public void prepare() throws Exception
{ {
client = new HttpClient(new SslContextFactory()); client = new HttpClient();
client.start(); client.start();
} }
@ -64,28 +63,20 @@ public class ExternalSiteTest
assumeCanConnectTo(host, port); assumeCanConnectTo(host, port);
final CountDownLatch latch1 = new CountDownLatch(1); final CountDownLatch latch1 = new CountDownLatch(1);
client.newRequest(host, port).send(new Response.CompleteListener() client.newRequest(host, port).send(result ->
{ {
@Override if (!result.isFailed() && result.getResponse().getStatus() == 200)
public void onComplete(Result result) latch1.countDown();
{
if (!result.isFailed() && result.getResponse().getStatus() == 200)
latch1.countDown();
}
}); });
assertTrue(latch1.await(10, TimeUnit.SECONDS)); assertTrue(latch1.await(10, TimeUnit.SECONDS));
// Try again the same URI, but without specifying the port // Try again the same URI, but without specifying the port
final CountDownLatch latch2 = new CountDownLatch(1); final CountDownLatch latch2 = new CountDownLatch(1);
client.newRequest("http://" + host).send(new Response.CompleteListener() client.newRequest("http://" + host).send(result ->
{ {
@Override assertTrue(result.isSucceeded());
public void onComplete(Result result) assertEquals(200, result.getResponse().getStatus());
{ latch2.countDown();
assertTrue(result.isSucceeded());
assertEquals(200, result.getResponse().getStatus());
latch2.countDown();
}
}); });
assertTrue(latch2.await(10, TimeUnit.SECONDS)); assertTrue(latch2.await(10, TimeUnit.SECONDS));
} }
@ -94,7 +85,7 @@ public class ExternalSiteTest
public void testExternalSSLSite() throws Exception public void testExternalSSLSite() throws Exception
{ {
client.stop(); client.stop();
client = new HttpClient(new SslContextFactory()); client = new HttpClient();
client.start(); client.start();
String host = "api-3t.paypal.com"; String host = "api-3t.paypal.com";
@ -104,14 +95,10 @@ public class ExternalSiteTest
assumeCanConnectTo(host, port); assumeCanConnectTo(host, port);
final CountDownLatch latch = new CountDownLatch(1); 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 if (result.isSucceeded() && result.getResponse().getStatus() == 200)
public void onComplete(Result result) latch.countDown();
{
if (result.isSucceeded() && result.getResponse().getStatus() == 200)
latch.countDown();
}
}); });
assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(latch.await(5, TimeUnit.SECONDS));
} }
@ -129,14 +116,7 @@ public class ExternalSiteTest
{ {
final CountDownLatch latch = new CountDownLatch(3); final CountDownLatch latch = new CountDownLatch(3);
client.newRequest(host, port) client.newRequest(host, port)
.onResponseFailure(new Response.FailureListener() .onResponseFailure((response, failure) -> latch.countDown())
{
@Override
public void onFailure(Response response, Throwable failure)
{
latch.countDown();
}
})
.send(new Response.Listener.Adapter() .send(new Response.Listener.Adapter()
{ {
@Override @Override
@ -180,7 +160,7 @@ public class ExternalSiteTest
} }
catch (Throwable x) catch (Throwable x)
{ {
assumeTrue(x == null, "Unable to connect"); assumeTrue(false, "Unable to connect");
} }
} }
} }

View File

@ -18,19 +18,16 @@
package org.eclipse.jetty.client; 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.io.IOException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.NetworkConnector;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server; 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.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; 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 * 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. * section 3.1) is configurable in SslContextFactory and works as expected.
@ -52,7 +52,7 @@ import org.junit.jupiter.api.Test;
@Disabled @Disabled
public class HostnameVerificationTest public class HostnameVerificationTest
{ {
private SslContextFactory clientSslContextFactory = new SslContextFactory(); private SslContextFactory.Client clientSslContextFactory = new SslContextFactory.Client();
private Server server; private Server server;
private HttpClient client; private HttpClient client;
private NetworkConnector connector; private NetworkConnector connector;
@ -64,7 +64,7 @@ public class HostnameVerificationTest
serverThreads.setName("server"); serverThreads.setName("server");
server = new Server(serverThreads); server = new Server(serverThreads);
SslContextFactory serverSslContextFactory = new SslContextFactory(); SslContextFactory.Server serverSslContextFactory = new SslContextFactory.Server();
serverSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); serverSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
serverSslContextFactory.setKeyStorePassword("storepwd"); serverSslContextFactory.setKeyStorePassword("storepwd");
connector = new ServerConnector(server, serverSslContextFactory); connector = new ServerConnector(server, serverSslContextFactory);
@ -72,7 +72,7 @@ public class HostnameVerificationTest
server.setHandler(new DefaultHandler() server.setHandler(new DefaultHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.getWriter().write("foobar"); response.getWriter().write("foobar");
@ -80,14 +80,19 @@ public class HostnameVerificationTest
}); });
server.start(); 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.setKeyStorePath("src/test/resources/keystore.jks");
clientSslContextFactory.setKeyStorePassword("storepwd"); clientSslContextFactory.setKeyStorePassword("storepwd");
ClientConnector clientConnector = new ClientConnector();
clientConnector.setSelectors(1);
clientConnector.setSslContextFactory(clientSslContextFactory);
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(clientSslContextFactory); clientConnector.setExecutor(clientThreads);
client.setExecutor(clientThreads);
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
client.start(); client.start();
} }
@ -112,9 +117,7 @@ public class HostnameVerificationTest
clientSslContextFactory.setEndpointIdentificationAlgorithm("HTTPS"); clientSslContextFactory.setEndpointIdentificationAlgorithm("HTTPS");
String uri = "https://localhost:" + connector.getLocalPort() + "/"; String uri = "https://localhost:" + connector.getLocalPort() + "/";
ExecutionException x = assertThrows(ExecutionException.class, ()->{ ExecutionException x = assertThrows(ExecutionException.class, ()-> client.GET(uri));
client.GET(uri);
});
Throwable cause = x.getCause(); Throwable cause = x.getCause();
assertThat(cause, Matchers.instanceOf(SSLHandshakeException.class)); assertThat(cause, Matchers.instanceOf(SSLHandshakeException.class));
Throwable root = cause.getCause().getCause(); Throwable root = cause.getCause().getCause();

View File

@ -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;
import org.eclipse.jetty.client.api.Response.Listener; import org.eclipse.jetty.client.api.Response.Listener;
import org.eclipse.jetty.client.api.Result; 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.BasicAuthentication;
import org.eclipse.jetty.client.util.DeferredContentProvider; import org.eclipse.jetty.client.util.DeferredContentProvider;
import org.eclipse.jetty.client.util.DigestAuthentication; import org.eclipse.jetty.client.util.DigestAuthentication;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.security.Authenticator; import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.ConstraintMapping; 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.security.authentication.DigestAuthenticator;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.IO; 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.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource; 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.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalToIgnoringCase; import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -137,7 +139,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
{ {
startBasic(scenario, new EmptyServerHandler()); startBasic(scenario, new EmptyServerHandler());
URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort()); 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 @ParameterizedTest
@ -155,7 +157,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
{ {
startDigest(scenario, new EmptyServerHandler()); startDigest(scenario, new EmptyServerHandler());
URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort()); 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 private void test_Authentication(final Scenario scenario, Authentication authentication) throws Exception
@ -227,16 +229,19 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
public void test_BasicAuthentication_ThenRedirect(Scenario scenario) throws Exception public void test_BasicAuthentication_ThenRedirect(Scenario scenario) throws Exception
{ {
startBasic(scenario, new AbstractHandler() startBasic(scenario, new EmptyServerHandler()
{ {
private final AtomicInteger requests = new AtomicInteger(); private final AtomicInteger requests = new AtomicInteger();
@Override @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); int r = requests.incrementAndGet();
if (requests.incrementAndGet() == 1) if (r == 1)
response.sendRedirect(URIUtil.newURI(scenario.getScheme(), request.getServerName(), request.getServerPort(), request.getRequestURI(), null)); {
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) @ArgumentsSource(ScenarioProvider.class)
public void test_Redirect_ThenBasicAuthentication(Scenario scenario) throws Exception public void test_Redirect_ThenBasicAuthentication(Scenario scenario) throws Exception
{ {
startBasic(scenario, new AbstractHandler() startBasic(scenario, new EmptyServerHandler()
{ {
@Override @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")) if (request.getRequestURI().endsWith("/redirect"))
response.sendRedirect(URIUtil.newURI(scenario.getScheme(), request.getServerName(), request.getServerPort(), "/secure", null)); 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)); 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); String authType = "Authenticate";
start(scenario, new EmptyServerHandler()
private final IntFunction<ByteBuffer> generator;
private GeneratingContentProvider(IntFunction<ByteBuffer> generator)
{ {
this.generator = generator; @Override
} protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
@Override
public long getLength()
{
return -1;
}
@Override
public boolean isReproducible()
{
return true;
}
@Override
public Iterator<ByteBuffer> iterator()
{
return new Iterator<ByteBuffer>()
{ {
private int index; // Always reply with a 401 to see if the client
public ByteBuffer current; // can handle an infinite authentication loop.
response.setStatus(HttpStatus.UNAUTHORIZED_401);
response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), authType);
}
});
@Override AuthenticationStore authenticationStore = client.getAuthenticationStore();
@SuppressWarnings("ReferenceEquality") URI uri = URI.create(scenario.getScheme() + "://localhost:" + connector.getLocalPort());
public boolean hasNext() 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++); return uri;
if (current == null)
current = DONE;
} }
return current != DONE;
}
@Override @Override
public ByteBuffer next() public void apply(Request request)
{ {
ByteBuffer result = current; }
current = null; };
if (result == null) }
throw new NoSuchElementException(); });
return result;
} ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
}; .scheme(scenario.getScheme())
} .send();
assertEquals(HttpStatus.UNAUTHORIZED_401, response.getStatus());
} }
@Test @Test
@ -801,4 +801,61 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
assertEquals("thermostat", headerInfo.getParameter("realm")); assertEquals("thermostat", headerInfo.getParameter("realm"));
assertEquals(headerInfo.getParameter("nonce"), "1523430383="); assertEquals(headerInfo.getParameter("nonce"), "1523430383=");
} }
private static class GeneratingContentProvider implements ContentProvider
{
private static final ByteBuffer DONE = ByteBuffer.allocate(0);
private final IntFunction<ByteBuffer> generator;
private GeneratingContentProvider(IntFunction<ByteBuffer> generator)
{
this.generator = generator;
}
@Override
public long getLength()
{
return -1;
}
@Override
public boolean isReproducible()
{
return true;
}
@Override
public Iterator<ByteBuffer> iterator()
{
return new Iterator<ByteBuffer>()
{
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;
}
};
}
}
} }

View File

@ -74,7 +74,7 @@ public class HttpClientFailureTest
startServer(new EmptyServerHandler()); startServer(new EmptyServerHandler());
final AtomicReference<HttpConnectionOverHTTP> connectionRef = new AtomicReference<>(); final AtomicReference<HttpConnectionOverHTTP> connectionRef = new AtomicReference<>();
client = new HttpClient(new HttpClientTransportOverHTTP() client = new HttpClient(new HttpClientTransportOverHTTP(1)
{ {
@Override @Override
protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise) protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise)
@ -83,15 +83,14 @@ public class HttpClientFailureTest
connectionRef.set(connection); connectionRef.set(connection);
return connection; return connection;
} }
}, null); });
client.start(); client.start();
assertThrows(ExecutionException.class, ()->{ assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.onRequestHeaders(request -> connectionRef.get().getEndPoint().close()) .onRequestHeaders(request -> connectionRef.get().getEndPoint().close())
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
.send(); .send());
});
DuplexConnectionPool connectionPool = (DuplexConnectionPool)connectionRef.get().getHttpDestination().getConnectionPool(); DuplexConnectionPool connectionPool = (DuplexConnectionPool)connectionRef.get().getHttpDestination().getConnectionPool();
assertEquals(0, connectionPool.getConnectionCount()); assertEquals(0, connectionPool.getConnectionCount());
@ -105,7 +104,7 @@ public class HttpClientFailureTest
startServer(new EmptyServerHandler()); startServer(new EmptyServerHandler());
final AtomicReference<HttpConnectionOverHTTP> connectionRef = new AtomicReference<>(); final AtomicReference<HttpConnectionOverHTTP> connectionRef = new AtomicReference<>();
client = new HttpClient(new HttpClientTransportOverHTTP() client = new HttpClient(new HttpClientTransportOverHTTP(1)
{ {
@Override @Override
protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise) protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise)
@ -114,7 +113,7 @@ public class HttpClientFailureTest
connectionRef.set(connection); connectionRef.set(connection);
return connection; return connection;
} }
}, null); });
client.start(); client.start();
final CountDownLatch commitLatch = new CountDownLatch(1); final CountDownLatch commitLatch = new CountDownLatch(1);

View File

@ -18,14 +18,6 @@
package org.eclipse.jetty.client; 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.io.IOException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -34,7 +26,9 @@ import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; 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.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.toolchain.test.IO;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource; 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 public class HttpClientRedirectTest extends AbstractHttpClientServerTest
{ {
@ParameterizedTest @ParameterizedTest
@ -128,14 +129,13 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
{ {
start(scenario, new RedirectHandler()); start(scenario, new RedirectHandler());
ExecutionException x = assertThrows(ExecutionException.class, ()->{ ExecutionException x = assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scenario.getScheme()) .scheme(scenario.getScheme())
.method(HttpMethod.DELETE) .method(HttpMethod.DELETE)
.path("/301/localhost/done") .path("/301/localhost/done")
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
.send(); .send());
});
HttpResponseException xx = (HttpResponseException)x.getCause(); HttpResponseException xx = (HttpResponseException)x.getCause();
Response response = xx.getResponse(); Response response = xx.getResponse();
assertNotNull(response); assertNotNull(response);
@ -170,13 +170,12 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
start(scenario, new RedirectHandler()); start(scenario, new RedirectHandler());
client.setMaxRedirects(1); client.setMaxRedirects(1);
ExecutionException x = assertThrows(ExecutionException.class, ()->{ ExecutionException x = assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scenario.getScheme()) .scheme(scenario.getScheme())
.path("/303/localhost/302/localhost/done") .path("/303/localhost/302/localhost/done")
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
.send(); .send());
});
HttpResponseException xx = (HttpResponseException)x.getCause(); HttpResponseException xx = (HttpResponseException)x.getCause();
Response response = xx.getResponse(); Response response = xx.getResponse();
assertNotNull(response); assertNotNull(response);
@ -269,12 +268,11 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
public void testRedirectWithWrongScheme(Scenario scenario) throws Exception public void testRedirectWithWrongScheme(Scenario scenario) throws Exception
{ {
start(scenario, new AbstractHandler() start(scenario, new EmptyServerHandler()
{ {
@Override @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.setStatus(303);
response.setHeader("Location", "ssh://localhost:" + connector.getLocalPort() + "/path"); response.setHeader("Location", "ssh://localhost:" + connector.getLocalPort() + "/path");
} }
@ -439,12 +437,11 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
public void testRedirectWithCorruptedBody(Scenario scenario) throws Exception public void testRedirectWithCorruptedBody(Scenario scenario) throws Exception
{ {
byte[] bytes = "ok".getBytes(StandardCharsets.UTF_8); byte[] bytes = "ok".getBytes(StandardCharsets.UTF_8);
start(scenario, new AbstractHandler() start(scenario, new EmptyServerHandler()
{ {
@Override @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")) if (target.startsWith("/redirect"))
{ {
response.setStatus(HttpStatus.SEE_OTHER_303); response.setStatus(HttpStatus.SEE_OTHER_303);
@ -471,6 +468,60 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
assertArrayEquals(bytes, response.getContent()); 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 private void testSameMethodRedirect(final Scenario scenario, final HttpMethod method, int redirectCode) throws Exception
{ {
testMethodRedirect(scenario, method, method, redirectCode); testMethodRedirect(scenario, method, method, redirectCode);
@ -519,10 +570,10 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
assertEquals(200, response.getStatus()); assertEquals(200, response.getStatus());
} }
private class RedirectHandler extends AbstractHandler private class RedirectHandler extends EmptyServerHandler
{ {
@Override @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 try
{ {
@ -551,10 +602,6 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
// Echo content back // Echo content back
IO.copy(request.getInputStream(), response.getOutputStream()); IO.copy(request.getInputStream(), response.getOutputStream());
} }
finally
{
baseRequest.setHandled(true);
}
} }
} }
} }

View File

@ -35,10 +35,12 @@ import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.client.api.ContentResponse; 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.HttpHeader;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnectionFactory; 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.SslClientConnectionFactory;
import org.eclipse.jetty.io.ssl.SslHandshakeListener; import org.eclipse.jetty.io.ssl.SslHandshakeListener;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
@ -66,7 +68,7 @@ public class HttpClientTLSTest
private ServerConnector connector; private ServerConnector connector;
private HttpClient client; 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(); ExecutorThreadPool serverThreads = new ExecutorThreadPool();
serverThreads.setName("server"); serverThreads.setName("server");
@ -79,22 +81,37 @@ public class HttpClientTLSTest
server.start(); 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(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(sslContextFactory); clientConnector.setExecutor(clientThreads);
client.setExecutor(clientThreads); client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
client.start(); 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.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
return sslContextFactory;
} }
@AfterEach @AfterEach
@ -109,7 +126,7 @@ public class HttpClientTLSTest
@Test @Test
public void testNoCommonTLSProtocol() throws Exception public void testNoCommonTLSProtocol() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
serverTLSFactory.setIncludeProtocols("TLSv1.3"); serverTLSFactory.setIncludeProtocols("TLSv1.3");
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
@ -123,7 +140,7 @@ public class HttpClientTLSTest
} }
}); });
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory.Client clientTLSFactory = createClientSslContextFactory();
clientTLSFactory.setIncludeProtocols("TLSv1.2"); clientTLSFactory.setIncludeProtocols("TLSv1.2");
startClient(clientTLSFactory); startClient(clientTLSFactory);
@ -150,7 +167,7 @@ public class HttpClientTLSTest
@Test @Test
public void testNoCommonTLSCiphers() throws Exception public void testNoCommonTLSCiphers() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
serverTLSFactory.setIncludeCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA"); serverTLSFactory.setIncludeCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA");
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
@ -164,7 +181,7 @@ public class HttpClientTLSTest
} }
}); });
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory.Client clientTLSFactory = createClientSslContextFactory();
clientTLSFactory.setExcludeCipherSuites(".*_SHA$"); clientTLSFactory.setExcludeCipherSuites(".*_SHA$");
startClient(clientTLSFactory); startClient(clientTLSFactory);
@ -191,7 +208,7 @@ public class HttpClientTLSTest
@Test @Test
public void testMismatchBetweenTLSProtocolAndTLSCiphersOnServer() throws Exception public void testMismatchBetweenTLSProtocolAndTLSCiphersOnServer() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
// TLS 1.1 protocol, but only TLS 1.2 ciphers. // TLS 1.1 protocol, but only TLS 1.2 ciphers.
serverTLSFactory.setIncludeProtocols("TLSv1.1"); serverTLSFactory.setIncludeProtocols("TLSv1.1");
serverTLSFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); 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); startClient(clientTLSFactory);
CountDownLatch clientLatch = new CountDownLatch(1); CountDownLatch clientLatch = new CountDownLatch(1);
@ -236,7 +253,7 @@ public class HttpClientTLSTest
@Test @Test
public void testMismatchBetweenTLSProtocolAndTLSCiphersOnClient() throws Exception public void testMismatchBetweenTLSProtocolAndTLSCiphersOnClient() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
CountDownLatch serverLatch = new CountDownLatch(1); 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. // TLS 1.1 protocol, but only TLS 1.2 ciphers.
clientTLSFactory.setIncludeProtocols("TLSv1.1"); clientTLSFactory.setIncludeProtocols("TLSv1.1");
clientTLSFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); clientTLSFactory.setIncludeCipherSuites("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
@ -278,7 +295,7 @@ public class HttpClientTLSTest
@Test @Test
public void testHandshakeSucceeded() throws Exception public void testHandshakeSucceeded() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
CountDownLatch serverLatch = new CountDownLatch(1); CountDownLatch serverLatch = new CountDownLatch(1);
@ -291,7 +308,7 @@ public class HttpClientTLSTest
} }
}); });
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory.Client clientTLSFactory = createClientSslContextFactory();
startClient(clientTLSFactory); startClient(clientTLSFactory);
CountDownLatch clientLatch = new CountDownLatch(1); CountDownLatch clientLatch = new CountDownLatch(1);
@ -317,7 +334,7 @@ public class HttpClientTLSTest
@Test @Test
public void testHandshakeSucceededWithSessionResumption() throws Exception public void testHandshakeSucceededWithSessionResumption() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
AtomicReference<byte[]> serverSession = new AtomicReference<>(); AtomicReference<byte[]> serverSession = new AtomicReference<>();
@ -330,7 +347,7 @@ public class HttpClientTLSTest
} }
}); });
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory.Client clientTLSFactory = createClientSslContextFactory();
startClient(clientTLSFactory); startClient(clientTLSFactory);
AtomicReference<byte[]> clientSession = new AtomicReference<>(); AtomicReference<byte[]> clientSession = new AtomicReference<>();
@ -397,10 +414,10 @@ public class HttpClientTLSTest
@Test @Test
public void testClientRawCloseDoesNotInvalidateSession() throws Exception public void testClientRawCloseDoesNotInvalidateSession() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory clientTLSFactory = createClientSslContextFactory();
clientTLSFactory.start(); clientTLSFactory.start();
String host = "localhost"; String host = "localhost";
@ -452,13 +469,17 @@ public class HttpClientTLSTest
@Test @Test
public void testServerRawCloseDetectedByClient() throws Exception public void testServerRawCloseDetectedByClient() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory serverTLSFactory = createServerSslContextFactory();
serverTLSFactory.start(); serverTLSFactory.start();
try (ServerSocket server = new ServerSocket(0)) try (ServerSocket server = new ServerSocket(0))
{ {
ClientConnector clientConnector = new ClientConnector();
clientConnector.setSelectors(1);
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(createSslContextFactory()) clientConnector.setExecutor(clientThreads);
clientConnector.setSslContextFactory(createClientSslContextFactory());
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector))
{ {
@Override @Override
protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory) protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
@ -468,7 +489,6 @@ public class HttpClientTLSTest
return ssl; return ssl;
} }
}; };
client.setExecutor(clientThreads);
client.start(); client.start();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -522,10 +542,10 @@ public class HttpClientTLSTest
@Test @Test
public void testHostNameVerificationFailure() throws Exception public void testHostNameVerificationFailure() throws Exception
{ {
SslContextFactory serverTLSFactory = createSslContextFactory(); SslContextFactory.Server serverTLSFactory = createServerSslContextFactory();
startServer(serverTLSFactory, new EmptyServerHandler()); startServer(serverTLSFactory, new EmptyServerHandler());
SslContextFactory clientTLSFactory = createSslContextFactory(); SslContextFactory.Client clientTLSFactory = createClientSslContextFactory();
// Make sure the host name is not verified at the TLS level. // Make sure the host name is not verified at the TLS level.
clientTLSFactory.setEndpointIdentificationAlgorithm(null); clientTLSFactory.setEndpointIdentificationAlgorithm(null);
// Add host name verification after the TLS handshake. // Add host name verification after the TLS handshake.

View File

@ -78,6 +78,7 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir; 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.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
@ -110,7 +112,6 @@ public class HttpClientTest extends AbstractHttpClientServerTest
{ {
public WorkDir testdir; public WorkDir testdir;
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
public void testStoppingClosesConnections(Scenario scenario) throws Exception public void testStoppingClosesConnections(Scenario scenario) throws Exception
@ -186,7 +187,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); response.getOutputStream().write(data);
baseRequest.setHandled(true); baseRequest.setHandled(true);
@ -211,7 +212,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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"); response.setCharacterEncoding("UTF-8");
ServletOutputStream output = response.getOutputStream(); ServletOutputStream output = response.getOutputStream();
@ -244,7 +245,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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"); response.setCharacterEncoding("UTF-8");
ServletOutputStream output = response.getOutputStream(); ServletOutputStream output = response.getOutputStream();
@ -281,7 +282,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -314,7 +315,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -348,7 +349,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
consume(request.getInputStream(), true); consume(request.getInputStream(), true);
@ -380,7 +381,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
consume(request.getInputStream(), true); consume(request.getInputStream(), true);
@ -411,7 +412,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
consume(request.getInputStream(), true); consume(request.getInputStream(), true);
@ -492,7 +493,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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")) if (target.endsWith("/one"))
baseRequest.getHttpChannel().getEndPoint().close(); baseRequest.getHttpChannel().getEndPoint().close();
@ -611,7 +612,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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 // Echo back
IO.copy(request.getInputStream(), response.getOutputStream()); IO.copy(request.getInputStream(), response.getOutputStream());
@ -633,7 +634,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@Override @Override
public Iterator<ByteBuffer> iterator() public Iterator<ByteBuffer> iterator()
{ {
return new Iterator<ByteBuffer>() return new Iterator<>()
{ {
@Override @Override
public boolean hasNext() public boolean hasNext()
@ -705,7 +706,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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 try
{ {
@ -721,13 +722,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final String host = "localhost"; final String host = "localhost";
final int port = connector.getLocalPort(); final int port = connector.getLocalPort();
assertThrows(TimeoutException.class, ()->{ assertThrows(TimeoutException.class, () ->
client.newRequest(host, port) client.newRequest(host, port)
.scheme(scenario.getScheme()) .scheme(scenario.getScheme())
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
.timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS)
.send(); .send());
});
// Make another request without specifying the idle timeout, should not fail // Make another request without specifying the idle timeout, should not fail
ContentResponse response = client.newRequest(host, port) ContentResponse response = client.newRequest(host, port)
@ -741,6 +741,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
@Tag("ipv6")
public void testSendToIPv6Address(Scenario scenario) throws Exception public void testSendToIPv6Address(Scenario scenario) throws Exception
{ {
start(scenario, new EmptyServerHandler()); start(scenario, new EmptyServerHandler());
@ -762,7 +763,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.setHeader(headerName, "X"); response.setHeader(headerName, "X");
@ -820,7 +821,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.getOutputStream().write(new byte[length]); response.getOutputStream().write(new byte[length]);
@ -881,14 +882,14 @@ public class HttpClientTest extends AbstractHttpClientServerTest
public void testConnectHostWithMultipleAddresses(Scenario scenario) throws Exception public void testConnectHostWithMultipleAddresses(Scenario scenario) throws Exception
{ {
startServer(scenario, new EmptyServerHandler()); startServer(scenario, new EmptyServerHandler());
startClient(scenario, null, client -> startClient(scenario, client ->
{ {
client.setSocketAddressResolver(new SocketAddressResolver.Async(client.getExecutor(), client.getScheduler(), 5000) client.setSocketAddressResolver(new SocketAddressResolver.Async(client.getExecutor(), client.getScheduler(), 5000)
{ {
@Override @Override
public void resolve(String host, int port, Promise<List<InetSocketAddress>> promise) public void resolve(String host, int port, Promise<List<InetSocketAddress>> promise)
{ {
super.resolve(host, port, new Promise<List<InetSocketAddress>>() super.resolve(host, port, new Promise<>()
{ {
@Override @Override
public void succeeded(List<InetSocketAddress> result) public void succeeded(List<InetSocketAddress> result)
@ -924,7 +925,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
ArrayList<String> userAgents = Collections.list(request.getHeaders("User-Agent")); ArrayList<String> userAgents = Collections.list(request.getHeaders("User-Agent"));
@ -958,7 +959,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
ArrayList<String> userAgents = Collections.list(request.getHeaders("User-Agent")); ArrayList<String> userAgents = Collections.list(request.getHeaders("User-Agent"));
@ -1160,7 +1161,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.getOutputStream().write(content); response.getOutputStream().write(content);
@ -1204,7 +1205,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
assertEquals(host, request.getServerName()); assertEquals(host, request.getServerName());
@ -1226,7 +1227,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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 // Send the headers at this point, then write the content
byte[] content = "TEST".getBytes("UTF-8"); byte[] content = "TEST".getBytes("UTF-8");
@ -1254,7 +1255,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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 // Send the headers at this point, then write the content
response.flushBuffer(); response.flushBuffer();
@ -1312,7 +1313,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
request.startAsync(); request.startAsync();
@ -1343,9 +1344,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
{ {
Assumptions.assumeTrue(HttpScheme.HTTP.is(scenario.getScheme())); Assumptions.assumeTrue(HttpScheme.HTTP.is(scenario.getScheme()));
ExecutionException e = assertThrows(ExecutionException.class, ()->{ ExecutionException e = assertThrows(ExecutionException.class, () ->
testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 1024); testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 1024));
});
assertThat(e.getCause(), instanceOf(BadMessageException.class)); assertThat(e.getCause(), instanceOf(BadMessageException.class));
assertThat(e.getCause().getMessage(), containsString("Unknown content")); assertThat(e.getCause().getMessage(), containsString("Unknown content"));
@ -1355,9 +1355,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@ArgumentsSource(NonSslScenarioProvider.class) @ArgumentsSource(NonSslScenarioProvider.class)
public void testBigContentDelimitedByEOFWithSlowRequestHTTP10(Scenario scenario) throws Exception public void testBigContentDelimitedByEOFWithSlowRequestHTTP10(Scenario scenario) throws Exception
{ {
ExecutionException e = assertThrows(ExecutionException.class, ()->{ ExecutionException e = assertThrows(ExecutionException.class, () ->
testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 128 * 1024); testContentDelimitedByEOFWithSlowRequest(scenario, HttpVersion.HTTP_1_0, 128 * 1024));
});
assertThat(e.getCause(), instanceOf(BadMessageException.class)); assertThat(e.getCause(), instanceOf(BadMessageException.class));
assertThat(e.getCause().getMessage(), containsString("Unknown content")); assertThat(e.getCause().getMessage(), containsString("Unknown content"));
@ -1391,7 +1390,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
// Send Connection: close to avoid that the server chunks the content with HTTP 1.1. // 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() start(scenario, new AbstractHandler()
{ {
@Override @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(); int count = requests.incrementAndGet();
if (count == maxRetries) if (count == maxRetries)
@ -1456,7 +1455,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
ServletOutputStream output = response.getOutputStream(); ServletOutputStream output = response.getOutputStream();
@ -1506,14 +1505,16 @@ public class HttpClientTest extends AbstractHttpClientServerTest
startServer(scenario, new AbstractHandler() startServer(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
} }
}); });
final AtomicBoolean open = new AtomicBoolean(); 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 @Override
protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise) protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, Promise<Connection> promise)
@ -1528,7 +1529,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
} }
}; };
} }
}, scenario.newSslContextFactory()); });
client.start(); client.start();
final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch latch = new CountDownLatch(2);
@ -1610,12 +1611,13 @@ public class HttpClientTest extends AbstractHttpClientServerTest
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
@Tag("ipv6")
public void test_IPv6_Host(Scenario scenario) throws Exception public void test_IPv6_Host(Scenario scenario) throws Exception
{ {
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.setContentType("text/plain"); response.setContentType("text/plain");
@ -1690,7 +1692,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(scenario, new AbstractHandler() start(scenario, new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
assertThat(request.getHeader("Host"), Matchers.notNullValue()); assertThat(request.getHeader("Host"), Matchers.notNullValue());
@ -1716,7 +1718,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
try (ServerSocket server = new ServerSocket(0)) try (ServerSocket server = new ServerSocket(0))
{ {
int idleTimeout = 2000; int idleTimeout = 2000;
startClient(scenario, null, httpClient -> startClient(scenario, httpClient ->
{ {
httpClient.setMaxConnectionsPerDestination(1); httpClient.setMaxConnectionsPerDestination(1);
httpClient.setIdleTimeout(idleTimeout); httpClient.setIdleTimeout(idleTimeout);

View File

@ -18,13 +18,6 @@
package org.eclipse.jetty.client; 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.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; 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.server.handler.AbstractHandler;
import org.eclipse.jetty.util.Fields; import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.URIUtil;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource; 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 public class HttpClientURITest extends AbstractHttpClientServerTest
{ {
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(ScenarioProvider.class) @ArgumentsSource(ScenarioProvider.class)
@Tag("ipv6")
public void testIPv6Host(Scenario scenario) throws Exception public void testIPv6Host(Scenario scenario) throws Exception
{ {
start(scenario, new EmptyServerHandler()); start(scenario, new EmptyServerHandler());

View File

@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -65,7 +64,7 @@ public class HttpClientUploadDuringServerShutdown
server.setHandler(new AbstractHandler() server.setHandler(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
@ -103,7 +102,7 @@ public class HttpClientUploadDuringServerShutdown
{ {
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
HttpClient client = new HttpClient(new HttpClientTransportOverHTTP(2), null); HttpClient client = new HttpClient(new HttpClientTransportOverHTTP(2));
client.setMaxConnectionsPerDestination(2); client.setMaxConnectionsPerDestination(2);
client.setIdleTimeout(10000); client.setIdleTimeout(10000);
client.setExecutor(clientThreads); client.setExecutor(clientThreads);
@ -142,7 +141,7 @@ public class HttpClientUploadDuringServerShutdown
server.setHandler(new AbstractHandler() server.setHandler(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
endPointRef.set(baseRequest.getHttpChannel().getEndPoint()); endPointRef.set(baseRequest.getHttpChannel().getEndPoint());
@ -210,7 +209,7 @@ public class HttpClientUploadDuringServerShutdown
} }
}; };
} }
}, null); });
client.setIdleTimeout(10000); client.setIdleTimeout(10000);
client.setExecutor(clientThreads); client.setExecutor(clientThreads);
client.start(); client.start();

View File

@ -53,9 +53,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
{ {
@Override @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); client.setStrictEventOrdering(false);
return client; return client;
} }

View File

@ -30,7 +30,7 @@ public class InsufficientThreadsDetectionTest
public void testInsufficientThreads() public void testInsufficientThreads()
{ {
QueuedThreadPool clientThreads = new QueuedThreadPool(1); QueuedThreadPool clientThreads = new QueuedThreadPool(1);
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(1), null); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(1));
httpClient.setExecutor(clientThreads); httpClient.setExecutor(clientThreads);
assertThrows(IllegalStateException.class, httpClient::start); assertThrows(IllegalStateException.class, httpClient::start);
} }
@ -39,14 +39,14 @@ public class InsufficientThreadsDetectionTest
public void testInsufficientThreadsForMultipleHttpClients() throws Exception public void testInsufficientThreadsForMultipleHttpClients() throws Exception
{ {
QueuedThreadPool clientThreads = new QueuedThreadPool(3); QueuedThreadPool clientThreads = new QueuedThreadPool(3);
HttpClient httpClient1 = new HttpClient(new HttpClientTransportOverHTTP(1), null); HttpClient httpClient1 = new HttpClient(new HttpClientTransportOverHTTP(1));
httpClient1.setExecutor(clientThreads); httpClient1.setExecutor(clientThreads);
httpClient1.start(); httpClient1.start();
assertThrows(IllegalStateException.class, () -> assertThrows(IllegalStateException.class, () ->
{ {
// Share the same thread pool with another instance. // 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.setExecutor(clientThreads);
httpClient2.start(); httpClient2.start();
}); });

View File

@ -93,7 +93,7 @@ public class LivelockTest
int count = 5; int count = 5;
HttpClientTransport transport = new HttpClientTransportOverHTTP(1); HttpClientTransport transport = new HttpClientTransportOverHTTP(1);
client = new HttpClient(transport, null); client = new HttpClient(transport);
client.setMaxConnectionsPerDestination(2 * count); client.setMaxConnectionsPerDestination(2 * count);
client.setMaxRequestsQueuedPerDestination(2 * count); client.setMaxRequestsQueuedPerDestination(2 * count);
client.setSocketAddressResolver(new SocketAddressResolver.Sync()); client.setSocketAddressResolver(new SocketAddressResolver.Sync());

View File

@ -18,12 +18,12 @@
package org.eclipse.jetty.client; 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.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class ProxyConfigurationTest public class ProxyConfigurationTest
{ {
@Test @Test
@ -68,6 +68,7 @@ public class ProxyConfigurationTest
} }
@Test @Test
@Tag("ipv6")
public void testProxyMatchesWithIncludesAndExcludesIPv6() throws Exception public void testProxyMatchesWithIncludesAndExcludesIPv6() throws Exception
{ {
HttpProxy proxy = new HttpProxy("host", 0); HttpProxy proxy = new HttpProxy("host", 0);

View File

@ -44,7 +44,7 @@ public class ServerConnectionCloseTest
{ {
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(new HttpClientTransportOverHTTP(1), null); client = new HttpClient(new HttpClientTransportOverHTTP(1));
client.setExecutor(clientThreads); client.setExecutor(clientThreads);
client.start(); client.start();
} }

View File

@ -33,6 +33,7 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@ -47,15 +48,20 @@ public class TLSServerConnectionCloseTest
private void startClient() throws Exception private void startClient() throws Exception
{ {
SslContextFactory sslContextFactory = new SslContextFactory(); ClientConnector clientConnector = new ClientConnector();
sslContextFactory.setEndpointIdentificationAlgorithm(""); clientConnector.setSelectors(1);
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
sslContextFactory.setEndpointIdentificationAlgorithm(null);
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
clientConnector.setSslContextFactory(sslContextFactory);
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(new HttpClientTransportOverHTTP(1), sslContextFactory); clientConnector.setExecutor(clientThreads);
client.setExecutor(clientThreads);
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
client.start(); client.start();
} }

View File

@ -42,13 +42,13 @@ import org.junit.jupiter.params.provider.ArgumentsSource;
public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest public class ValidatingConnectionPoolTest extends AbstractHttpClientServerTest
{ {
@Override @Override
public HttpClient newHttpClient(Scenario scenario, HttpClientTransport transport) public HttpClient newHttpClient(HttpClientTransport transport)
{ {
long timeout = 1000; long timeout = 1000;
transport.setConnectionPoolFactory(destination -> transport.setConnectionPoolFactory(destination ->
new ValidatingConnectionPool(destination, destination.getHttpClient().getMaxConnectionsPerDestination(), destination, destination.getHttpClient().getScheduler(), timeout)); new ValidatingConnectionPool(destination, destination.getHttpClient().getMaxConnectionsPerDestination(), destination, destination.getHttpClient().getScheduler(), timeout));
return super.newHttpClient(scenario, transport); return super.newHttpClient(transport);
} }
@ParameterizedTest @ParameterizedTest

View File

@ -186,7 +186,7 @@ public class HttpDestinationOverHTTPTest extends AbstractHttpClientServerTest
{ {
startServer(scenario, new EmptyServerHandler()); startServer(scenario, new EmptyServerHandler());
long idleTimeout = 1000; 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()))) try(HttpDestination destination = new DuplexHttpDestination(client, new Origin("http", "localhost", connector.getLocalPort())))
{ {

View File

@ -18,11 +18,6 @@
package org.eclipse.jetty.client.ssl; 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.security.cert.Certificate;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; 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.EmptyServerHandler;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.ssl.SslHandshakeListener; import org.eclipse.jetty.io.ssl.SslHandshakeListener;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server; 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.eclipse.jetty.util.thread.QueuedThreadPool;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; 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 * In order to work, client authentication needs a certificate
* signed by a CA that also signed the server certificate. * signed by a CA that also signed the server certificate.
@ -59,7 +60,7 @@ public class NeedWantClientAuthTest
private ServerConnector connector; private ServerConnector connector;
private HttpClient client; 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(); QueuedThreadPool serverThreads = new QueuedThreadPool();
serverThreads.setName("server"); serverThreads.setName("server");
@ -72,19 +73,21 @@ public class NeedWantClientAuthTest
server.start(); 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(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); clientThreads.setName("client");
client = new HttpClient(sslContextFactory); clientConnector.setExecutor(clientThreads);
client.setExecutor(clientThreads); clientConnector.setSslContextFactory(sslContextFactory);
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
client.start(); client.start();
} }
private SslContextFactory createSslContextFactory() private SslContextFactory.Server createServerSslContextFactory()
{ {
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setEndpointIdentificationAlgorithm("");
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
return sslContextFactory; return sslContextFactory;
@ -102,11 +105,11 @@ public class NeedWantClientAuthTest
@Test @Test
public void testWantClientAuthWithoutAuth() throws Exception public void testWantClientAuthWithoutAuth() throws Exception
{ {
SslContextFactory serverSSL = createSslContextFactory(); SslContextFactory.Server serverSSL = createServerSslContextFactory();
serverSSL.setWantClientAuth(true); serverSSL.setWantClientAuth(true);
startServer(serverSSL, new EmptyServerHandler()); startServer(serverSSL, new EmptyServerHandler());
SslContextFactory clientSSL = new SslContextFactory(true); SslContextFactory.Client clientSSL = new SslContextFactory.Client(true);
startClient(clientSSL); startClient(clientSSL);
ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort()) ContentResponse response = client.newRequest("https://localhost:" + connector.getLocalPort())
@ -119,7 +122,7 @@ public class NeedWantClientAuthTest
@Test @Test
public void testWantClientAuthWithAuth() throws Exception public void testWantClientAuthWithAuth() throws Exception
{ {
SslContextFactory serverSSL = createSslContextFactory(); SslContextFactory.Server serverSSL = createServerSslContextFactory();
serverSSL.setWantClientAuth(true); serverSSL.setWantClientAuth(true);
startServer(serverSSL, new EmptyServerHandler()); startServer(serverSSL, new EmptyServerHandler());
CountDownLatch handshakeLatch = new CountDownLatch(1); 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.setKeyStorePath("src/test/resources/client_keystore.jks");
clientSSL.setKeyStorePassword("storepwd"); clientSSL.setKeyStorePassword("storepwd");
startClient(clientSSL); startClient(clientSSL);
@ -166,11 +169,11 @@ public class NeedWantClientAuthTest
// The server still sends bad_certificate to the client, but the client handshake has already // The server still sends bad_certificate to the client, but the client handshake has already
// completed successfully its TLS handshake. // completed successfully its TLS handshake.
SslContextFactory serverSSL = createSslContextFactory(); SslContextFactory.Server serverSSL = createServerSslContextFactory();
serverSSL.setNeedClientAuth(true); serverSSL.setNeedClientAuth(true);
startServer(serverSSL, new EmptyServerHandler()); startServer(serverSSL, new EmptyServerHandler());
SslContextFactory clientSSL = new SslContextFactory(true); SslContextFactory.Client clientSSL = new SslContextFactory.Client(true);
startClient(clientSSL); startClient(clientSSL);
CountDownLatch handshakeLatch = new CountDownLatch(1); CountDownLatch handshakeLatch = new CountDownLatch(1);
client.addBean(new SslHandshakeListener() client.addBean(new SslHandshakeListener()
@ -210,7 +213,7 @@ public class NeedWantClientAuthTest
@Test @Test
public void testNeedClientAuthWithAuth() throws Exception public void testNeedClientAuthWithAuth() throws Exception
{ {
SslContextFactory serverSSL = createSslContextFactory(); SslContextFactory.Server serverSSL = createServerSslContextFactory();
serverSSL.setNeedClientAuth(true); serverSSL.setNeedClientAuth(true);
startServer(serverSSL, new EmptyServerHandler()); startServer(serverSSL, new EmptyServerHandler());
CountDownLatch handshakeLatch = new CountDownLatch(1); 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.setKeyStorePath("src/test/resources/client_keystore.jks");
clientSSL.setKeyStorePassword("storepwd"); clientSSL.setKeyStorePassword("storepwd");
startClient(clientSSL); startClient(clientSSL);

View File

@ -38,9 +38,11 @@ import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request; 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.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@ -61,7 +63,7 @@ public class SslBytesClientTest extends SslBytesTest
{ {
private ExecutorService threadPool; private ExecutorService threadPool;
private HttpClient client; private HttpClient client;
private SslContextFactory sslContextFactory; private SslContextFactory.Client sslContextFactory;
private SSLServerSocket acceptor; private SSLServerSocket acceptor;
private SimpleProxy proxy; private SimpleProxy proxy;
@ -70,8 +72,11 @@ public class SslBytesClientTest extends SslBytesTest
{ {
threadPool = Executors.newCachedThreadPool(); threadPool = Executors.newCachedThreadPool();
sslContextFactory = new SslContextFactory(true); ClientConnector clientConnector = new ClientConnector();
client = new HttpClient(sslContextFactory); clientConnector.setSelectors(1);
sslContextFactory = new SslContextFactory.Client(true);
clientConnector.setSslContextFactory(sslContextFactory);
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
client.setMaxConnectionsPerDestination(1); client.setMaxConnectionsPerDestination(1);
File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks");
sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); 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 // Trigger a read to have the server write the final renegotiation steps
server.setSoTimeout(100); server.setSoTimeout(100);
assertThrows(SocketTimeoutException.class, ()->serverInput.read()); assertThrows(SocketTimeoutException.class, () -> serverInput.read());
// Renegotiation Handshake // Renegotiation Handshake
record = proxy.readFromServer(); record = proxy.readFromServer();

View File

@ -100,7 +100,7 @@ public class SslBytesServerTest extends SslBytesTest
private final int idleTimeout = 2000; private final int idleTimeout = 2000;
private ExecutorService threadPool; private ExecutorService threadPool;
private Server server; private Server server;
private SslContextFactory sslContextFactory; private SslContextFactory.Server sslContextFactory;
private int serverPort; private int serverPort;
private SSLContext sslContext; private SSLContext sslContext;
private SimpleProxy proxy; private SimpleProxy proxy;
@ -119,7 +119,7 @@ public class SslBytesServerTest extends SslBytesTest
serverEndPoint.set(null); serverEndPoint.set(null);
File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks");
sslContextFactory = new SslContextFactory(); sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.client.ssl; package org.eclipse.jetty.client.ssl;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.File; import java.io.File;
import java.nio.ByteBuffer; 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.BufferUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class SslConnectionTest public class SslConnectionTest
{ {
@Test @Test
public void testSslConnectionClosedBeforeFill() throws Exception public void testSslConnectionClosedBeforeFill() throws Exception
{ {
File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks"); File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath()); sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.start(); sslContextFactory.start();

View File

@ -22,6 +22,7 @@ import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node; import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Callback;
public class StandardDeployer implements AppLifeCycle.Binding public class StandardDeployer implements AppLifeCycle.Binding
{ {
@ -37,9 +38,10 @@ public class StandardDeployer implements AppLifeCycle.Binding
{ {
ContextHandler handler = app.getContextHandler(); ContextHandler handler = app.getContextHandler();
if (handler == null) if (handler == null)
{
throw new NullPointerException("No Handler created for App: " + app); 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();
} }
} }

View File

@ -21,17 +21,12 @@ package org.eclipse.jetty.deploy.bindings;
import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node; 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.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class StandardUndeployer implements AppLifeCycle.Binding public class StandardUndeployer implements AppLifeCycle.Binding
{ {
private static final Logger LOG = Log.getLogger(StandardUndeployer.class);
@Override @Override
public String[] getBindingTargets() public String[] getBindingTargets()
{ {
@ -42,33 +37,11 @@ public class StandardUndeployer implements AppLifeCycle.Binding
@Override @Override
public void processBinding(Node node, App app) throws Exception public void processBinding(Node node, App app) throws Exception
{ {
ContextHandler handler = app.getContextHandler(); ContextHandlerCollection contexts = app.getDeploymentManager().getContexts();
ContextHandlerCollection chcoll = app.getDeploymentManager().getContexts(); ContextHandler context = app.getContextHandler();
Callback.Completable blocker = new Callback.Completable();
recursiveRemoveContext(chcoll,handler); contexts.undeployHandler(context, blocker);
} blocker.get();
context.destroy();
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);
}
}
} }
} }

View File

@ -290,8 +290,8 @@ Similarly, in code:
[source, java, subs="{sub-order}"] [source, java, subs="{sub-order}"]
---- ----
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(); sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("secret"); sslContextFactory.setKeyStorePassword("secret");
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi"); JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi");

View File

@ -472,7 +472,7 @@ This adds a `SecureRequestCustomizer` which adds SSL Session IDs and certificate
==== SSL Context Configuration ==== SSL Context Configuration
The SSL/TLS connectors for HTTPS and HTTP/2 require a certificate to establish a secure connection. 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`]. 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]. Read more about SSL keystores in link:#configuring-ssl[Configuring SSL].

View File

@ -55,9 +55,8 @@ You can re-enable these by re-declaring the ciphers you want excluded in code:
[source, java, subs="{sub-order}"] [source, java, subs="{sub-order}"]
---- ----
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setExcludeCipherSuites( sslContextFactory.setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$");
"^.*_(MD5|SHA|SHA1)$");
---- ----
If, after making these changes, you still have issues using these ciphers they are likely being blocked at the JVM level. 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-sslcontextfactory]]
==== Configuring the Jetty 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: 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 * https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol[OCSP] Support
* Client Authentication 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. 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()); Security.addProvider(new OpenSSLProvider());
... ...
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("path/to/keystore"); sslContextFactory.setKeyStorePath("path/to/keystore");
sslContextFactory.setKeyStorePassword("CleverKeyStorePassword"); sslContextFactory.setKeyStorePassword("CleverKeyStorePassword");
sslContextFactory.setKeyManagerPassword("OBF:VerySecretManagerPassword"); sslContextFactory.setKeyManagerPassword("OBF:VerySecretManagerPassword");
@ -790,7 +789,7 @@ To do this, first create a new `${jetty.base}/etc/tweak-ssl.xml` file (this can
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_3.dtd"> "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- Tweak SsslContextFactory Includes / Excludes --> <!-- Tweak SsslContextFactory Includes / Excludes -->
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"> <Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
<!-- Mitigate SLOTH Attack --> <!-- Mitigate SLOTH Attack -->
<Call name="addExcludeCipherSuites"> <Call name="addExcludeCipherSuites">
<Arg> <Arg>

View File

@ -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. 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. 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}"] [source, java, subs="{sub-order}"]
---- ----
// Instantiate and configure the SslContextFactory // Instantiate and configure the SslContextFactory
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
// Instantiate HttpClient with the SslContextFactory // Instantiate HttpClient with the SslContextFactory
HttpClient httpClient = new HttpClient(sslContextFactory); HttpClient httpClient = new HttpClient(sslContextFactory);

View File

@ -116,7 +116,7 @@ public class FastCGIProxyServlet extends AsyncProxyServlet.Transparent
String value = config.getInitParameter("selectors"); String value = config.getInitParameter("selectors");
if (value != null) if (value != null)
selectors = Integer.parseInt(value); selectors = Integer.parseInt(value);
return new HttpClient(new ProxyHttpClientTransportOverFCGI(selectors, scriptRoot), null); return new HttpClient(new ProxyHttpClientTransportOverFCGI(selectors, scriptRoot));
} }
@Override @Override

View File

@ -76,7 +76,7 @@ public abstract class AbstractHttpClientServerTest
connectionLeaks.incrementAndGet(); connectionLeaks.incrementAndGet();
} }
}); });
client = new HttpClient(transport, null); client = new HttpClient(transport);
client.setExecutor(executor); client.setExecutor(executor);
if (clientBufferPool == null) if (clientBufferPool == null)
clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());

View File

@ -40,7 +40,7 @@ public class ExternalFastCGIServerTest
{ {
// Assume a FastCGI server is listening on localhost:9000 // 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(); client.start();
ContentResponse response = client.newRequest("localhost", 9000) ContentResponse response = client.newRequest("localhost", 9000)

View File

@ -18,14 +18,6 @@
package org.eclipse.jetty.fcgi.server; 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.EOFException;
import java.io.IOException; import java.io.IOException;
import java.net.URI; 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.ContentResponse;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; 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.BytesContentProvider;
import org.eclipse.jetty.client.util.DeferredContentProvider; import org.eclipse.jetty.client.util.DeferredContentProvider;
import org.eclipse.jetty.client.util.FutureResponseListener; 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.toolchain.test.IO;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.util.log.StacklessLogging;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty; 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 public class HttpClientTest extends AbstractHttpClientServerTest
{ {
@Test @Test
@ -85,7 +84,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); response.getOutputStream().write(data);
baseRequest.setHandled(true); baseRequest.setHandled(true);
@ -113,7 +112,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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 // Setting the Content-Length triggers the HTTP
// content mode for response content parsing, // content mode for response content parsing,
@ -142,7 +141,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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"); response.setCharacterEncoding("UTF-8");
ServletOutputStream output = response.getOutputStream(); ServletOutputStream output = response.getOutputStream();
@ -174,7 +173,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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"); response.setCharacterEncoding("UTF-8");
ServletOutputStream output = response.getOutputStream(); ServletOutputStream output = response.getOutputStream();
@ -210,7 +209,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -241,7 +240,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -273,7 +272,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -306,7 +305,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
String value = request.getParameter(paramName); String value = request.getParameter(paramName);
@ -340,16 +339,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new EmptyServerHandler()); start(new EmptyServerHandler());
ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort()) ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort())
.onRequestContent(new Request.ContentListener() .onRequestContent((request, buffer) ->
{ {
@Override byte[] bytes = new byte[buffer.remaining()];
public void onContent(Request request, ByteBuffer buffer) buffer.get(bytes);
{ if (!Arrays.equals(content, bytes))
byte[] bytes = new byte[buffer.remaining()]; request.abort(new Exception());
buffer.get(bytes);
if (!Arrays.equals(content, bytes))
request.abort(new Exception());
}
}) })
.content(new BytesContentProvider(content)) .content(new BytesContentProvider(content))
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
@ -366,16 +361,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final AtomicInteger progress = new AtomicInteger(); final AtomicInteger progress = new AtomicInteger();
ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort()) ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort())
.onRequestContent(new Request.ContentListener() .onRequestContent((request, buffer) ->
{ {
@Override byte[] bytes = new byte[buffer.remaining()];
public void onContent(Request request, ByteBuffer buffer) assertEquals(1, bytes.length);
{ buffer.get(bytes);
byte[] bytes = new byte[buffer.remaining()]; assertEquals(bytes[0], progress.getAndIncrement());
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})) .content(new BytesContentProvider(new byte[]{0}, new byte[]{1}, new byte[]{2}, new byte[]{3}, new byte[]{4}))
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
@ -398,7 +389,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.setHeader("Content-Encoding", "gzip"); response.setHeader("Content-Encoding", "gzip");
@ -425,7 +416,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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 try
{ {
@ -441,13 +432,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final String host = "localhost"; final String host = "localhost";
final int port = connector.getLocalPort(); final int port = connector.getLocalPort();
assertThrows(TimeoutException.class, ()->{ assertThrows(TimeoutException.class, () ->
client.newRequest(host, port) client.newRequest(host, port)
.scheme(scheme) .scheme(scheme)
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS) .idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
.timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS)
.send(); .send());
});
// Make another request without specifying the idle timeout, should not fail // Make another request without specifying the idle timeout, should not fail
ContentResponse response = client.newRequest(host, port) ContentResponse response = client.newRequest(host, port)
@ -466,7 +456,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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 try
{ {
@ -482,13 +472,12 @@ public class HttpClientTest extends AbstractHttpClientServerTest
connector.setIdleTimeout(idleTimeout); connector.setIdleTimeout(idleTimeout);
ExecutionException x = assertThrows(ExecutionException.class, ()->{ ExecutionException x = assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS) .idleTimeout(4 * idleTimeout, TimeUnit.MILLISECONDS)
.timeout(3 * idleTimeout, TimeUnit.MILLISECONDS) .timeout(3 * idleTimeout, TimeUnit.MILLISECONDS)
.send(); .send());
});
assertThat(x.getCause(), instanceOf(EOFException.class)); assertThat(x.getCause(), instanceOf(EOFException.class));
connector.setIdleTimeout(5 * idleTimeout); connector.setIdleTimeout(5 * idleTimeout);
@ -505,6 +494,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
} }
@Test @Test
@Tag("ipv6")
public void testSendToIPv6Address() throws Exception public void testSendToIPv6Address() throws Exception
{ {
start(new EmptyServerHandler()); start(new EmptyServerHandler());
@ -525,7 +515,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.getOutputStream().write(new byte[length]); response.getOutputStream().write(new byte[length]);
@ -562,7 +552,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
request.startAsync(); request.startAsync();
@ -573,14 +563,10 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final CountDownLatch completeLatch = new CountDownLatch(1); final CountDownLatch completeLatch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.send(new Response.CompleteListener() .send(result ->
{ {
@Override if (result.isFailed())
public void onComplete(Result result) completeLatch.countDown();
{
if (result.isFailed())
completeLatch.countDown();
}
}); });
assertTrue(latch.await(5, TimeUnit.SECONDS)); assertTrue(latch.await(5, TimeUnit.SECONDS));
@ -597,7 +583,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
// Promise some content, then flush the headers, then fail to send the content. // 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)) try (StacklessLogging ignore = new StacklessLogging(org.eclipse.jetty.server.HttpChannel.class))
{ {
assertThrows(ExecutionException.class, () -> { assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.timeout(60, TimeUnit.SECONDS) .timeout(60, TimeUnit.SECONDS)
.send(); .send());
});
} }
} }
@ -637,7 +622,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.setHeader("Connection", "close"); response.setHeader("Connection", "close");
@ -667,7 +652,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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(); ServletOutputStream output = response.getOutputStream();
output.write(65); output.write(65);
@ -682,24 +667,13 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final CountDownLatch completeLatch = new CountDownLatch(1); final CountDownLatch completeLatch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.onResponseContentAsync(new Response.AsyncContentListener() .onResponseContentAsync((response, content, callback) ->
{ {
@Override contentCount.incrementAndGet();
public void onContent(Response response, ByteBuffer content, Callback callback) callbackRef.set(callback);
{ contentLatch.get().countDown();
contentCount.incrementAndGet();
callbackRef.set(callback);
contentLatch.get().countDown();
}
}) })
.send(new Response.CompleteListener() .send(result -> completeLatch.countDown());
{
@Override
public void onComplete(Result result)
{
completeLatch.countDown();
}
});
assertTrue(contentLatch.get().await(5, TimeUnit.SECONDS)); assertTrue(contentLatch.get().await(5, TimeUnit.SECONDS));
Callback callback = callbackRef.get(); Callback callback = callbackRef.get();

View File

@ -36,8 +36,7 @@ public class DrupalHTTP2FastCGIProxyServer
{ {
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setEndpointIdentificationAlgorithm("");
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");

View File

@ -18,20 +18,17 @@
package org.eclipse.jetty.fcgi.server.proxy; 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 java.util.EnumSet;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; 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.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder; 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.AfterEach;
import org.junit.jupiter.api.Test; 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 public class TryFilesFilterTest
{ {
private Server server; private Server server;
@ -55,13 +55,10 @@ public class TryFilesFilterTest
connector = new ServerConnector(server); connector = new ServerConnector(server);
server.addConnector(connector); server.addConnector(connector);
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server serverSslContextFactory = new SslContextFactory.Server();
sslContextFactory.setEndpointIdentificationAlgorithm(""); serverSslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); serverSslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyStorePassword("storepwd"); sslConnector = new ServerConnector(server, serverSslContextFactory);
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
sslContextFactory.setTrustStorePassword("storepwd");
sslConnector = new ServerConnector(server, sslContextFactory);
server.addConnector(sslConnector); server.addConnector(sslConnector);
ServletContextHandler context = new ServletContextHandler(server, "/"); ServletContextHandler context = new ServletContextHandler(server, "/");
@ -72,7 +69,15 @@ public class TryFilesFilterTest
context.addServlet(new ServletHolder(servlet), "/*"); 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.addBean(client);
server.start(); server.start();
@ -91,7 +96,7 @@ public class TryFilesFilterTest
prepare(new HttpServlet() prepare(new HttpServlet()
{ {
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException protected void doGet(HttpServletRequest req, HttpServletResponse resp)
{ {
assertTrue("https".equalsIgnoreCase(req.getScheme())); assertTrue("https".equalsIgnoreCase(req.getScheme()));
assertTrue(req.isSecure()); assertTrue(req.isSecure());

View File

@ -43,8 +43,7 @@ public class WordPressHTTP2FastCGIProxyServer
{ {
int tlsPort = 8443; int tlsPort = 8443;
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setEndpointIdentificationAlgorithm("");
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks"); sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks"); sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");

View File

@ -13,7 +13,7 @@ session-store
sessions sessions
[files] [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] [xml]
etc/sessions/hazelcast/default.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.hazelcastInstanceName=JETTY_DISTRIBUTED_SESSION_INSTANCE
#jetty.session.hazelcast.configurationLocation= #jetty.session.hazelcast.configurationLocation=
jetty.session.gracePeriod.seconds=3600 jetty.session.gracePeriod.seconds=3600
jetty.session.savePeriod.seconds=0 jetty.session.savePeriod.seconds=0

View File

@ -13,8 +13,8 @@ session-store
sessions sessions
[files] [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
maven://com.hazelcast/hazelcast-client/3.8.2|lib/hazelcast/hazelcast-client-3.8.2.jar maven://com.hazelcast/hazelcast-client/3.9.3|lib/hazelcast/hazelcast-client-3.9.3.jar
[xml] [xml]
etc/sessions/hazelcast/remote.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.onlyClient=true
#jetty.session.hazelcast.configurationLocation= #jetty.session.hazelcast.configurationLocation=
jetty.session.gracePeriod.seconds=3600 jetty.session.gracePeriod.seconds=3600
jetty.session.savePeriod.seconds=0 jetty.session.savePeriod.seconds=0

View File

@ -28,6 +28,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_INSENSITIVE_METHOD; import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_INSENSITIVE_METHOD;
@ -1975,6 +1976,7 @@ public class HttpParserTest
} }
@Test @Test
@Tag("ipv6")
public void testIPv6Host() throws Exception public void testIPv6Host() throws Exception
{ {
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(
@ -2056,6 +2058,7 @@ public class HttpParserTest
} }
@Test @Test
@Tag("ipv6")
public void testIPv6HostPort() throws Exception public void testIPv6HostPort() throws Exception
{ {
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(

View File

@ -65,7 +65,7 @@ public class AbstractTest
protected void prepareClient() throws Exception protected void prepareClient() throws Exception
{ {
client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()), null); client = new HttpClient(new HttpClientTransportOverHTTP2(new HTTP2Client()));
QueuedThreadPool clientExecutor = new QueuedThreadPool(); QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client"); clientExecutor.setName("client");
client.setExecutor(clientExecutor); client.setExecutor(clientExecutor);

View File

@ -18,10 +18,8 @@
package org.eclipse.jetty.http2.client.http; package org.eclipse.jetty.http2.client.http;
import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.HTTP2Cipher;
import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
@ -68,7 +67,7 @@ public class DirectHTTP2OverTLSTest
HttpConfiguration httpsConfig = new HttpConfiguration(); HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.addCustomizer(new SecureRequestCustomizer()); httpsConfig.addCustomizer(new SecureRequestCustomizer());
ConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig); 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); connector = new ServerConnector(server, 1, 1, ssl, h2);
server.addConnector(connector); server.addConnector(connector);
server.setHandler(handler); server.setHandler(handler);
@ -77,14 +76,14 @@ public class DirectHTTP2OverTLSTest
private void startClient() throws Exception private void startClient() throws Exception
{ {
ClientConnector clientConnector = new ClientConnector();
QueuedThreadPool clientThreads = new QueuedThreadPool(); QueuedThreadPool clientThreads = new QueuedThreadPool();
clientThreads.setName("client"); 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); transport.setUseALPN(false);
SslContextFactory sslContextFactory = newSslContextFactory(); client = new HttpClient(transport);
sslContextFactory.setEndpointIdentificationAlgorithm(null);
client = new HttpClient(transport, sslContextFactory);
client.setExecutor(clientThreads);
client.start(); client.start();
} }
@ -97,14 +96,27 @@ public class DirectHTTP2OverTLSTest
server.stop(); 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.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setUseCipherSuitesOrder(true); sslContextFactory.setUseCipherSuitesOrder(true);
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR); sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
return sslContextFactory;
} }
@Test @Test
@ -115,7 +127,7 @@ public class DirectHTTP2OverTLSTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
} }

View File

@ -18,16 +18,6 @@
package org.eclipse.jetty.http2.client.http; 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.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.ServerSocket; import java.net.ServerSocket;
@ -48,7 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.parser.ServerParser;
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory; import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request; 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.Disabled;
import org.junit.jupiter.api.Test; 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 public class HttpClientTransportOverHTTP2Test extends AbstractTest
{ {
@Test @Test
public void testPropertiesAreForwarded() throws Exception public void testPropertiesAreForwarded() throws Exception
{ {
HTTP2Client http2Client = new HTTP2Client(); HTTP2Client http2Client = new HTTP2Client();
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), null); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client));
Executor executor = new QueuedThreadPool(); Executor executor = new QueuedThreadPool();
httpClient.setExecutor(executor); httpClient.setExecutor(executor);
httpClient.setConnectTimeout(13); httpClient.setConnectTimeout(13);
@ -133,11 +132,10 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
} }
}); });
assertThrows(ExecutionException.class, ()->{ assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.onRequestCommit(request -> request.abort(new Exception("explicitly_aborted_by_test"))) .onRequestCommit(request -> request.abort(new Exception("explicitly_aborted_by_test")))
.send(); .send());
});
assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
} }
@ -172,11 +170,10 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
} }
}); });
assertThrows(ExecutionException.class, ()->{ assertThrows(ExecutionException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.onResponseContent((response, buffer) -> response.abort(new Exception("explicitly_aborted_by_test"))) .onResponseContent((response, buffer) -> response.abort(new Exception("explicitly_aborted_by_test")))
.send(); .send());
});
assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
} }
@ -186,7 +183,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
HttpVersion version = HttpVersion.fromString(request.getProtocol()); HttpVersion version = HttpVersion.fromString(request.getProtocol());
@ -274,7 +271,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
lastStream.set(frame.getLastStreamId()); lastStream.set(frame.getLastStreamId());
latch.countDown(); latch.countDown();
} }
}, null); });
QueuedThreadPool clientExecutor = new QueuedThreadPool(); QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client"); clientExecutor.setName("client");
client.setExecutor(clientExecutor); client.setExecutor(clientExecutor);
@ -312,7 +309,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
assertEquals(path, request.getRequestURI()); assertEquals(path, request.getRequestURI());
@ -336,7 +333,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler() start(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
assertEquals(path, request.getRequestURI()); assertEquals(path, request.getRequestURI());
@ -381,12 +378,11 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
client.setIdleTimeout(idleTimeout); client.setIdleTimeout(idleTimeout);
client.start(); client.start();
assertThrows(TimeoutException.class, ()->{ assertThrows(TimeoutException.class, () ->
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
// Make sure the connection idle times out, not the stream. // Make sure the connection idle times out, not the stream.
.idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS) .idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS)
.send(); .send());
});
assertTrue(resetLatch.await(5, TimeUnit.SECONDS)); assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
} }
@ -436,7 +432,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
sessions.add(session); sessions.add(session);
return super.newHttpConnection(destination, session); return super.newHttpConnection(destination, session);
} }
}, null); });
QueuedThreadPool clientExecutor = new QueuedThreadPool(); QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client"); clientExecutor.setName("client");
client.setExecutor(clientExecutor); client.setExecutor(clientExecutor);
@ -600,12 +596,13 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
@Test @Test
public void testExternalServer() throws Exception public void testExternalServer() throws Exception
{ {
HTTP2Client http2Client = new HTTP2Client(); ClientConnector clientConnector = new ClientConnector();
SslContextFactory sslContextFactory = new SslContextFactory(); HTTP2Client http2Client = new HTTP2Client(clientConnector);
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
clientConnector.setSslContextFactory(sslContextFactory);
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client));
Executor executor = new QueuedThreadPool(); Executor executor = new QueuedThreadPool();
httpClient.setExecutor(executor); clientConnector.setExecutor(executor);
httpClient.start(); httpClient.start();
// ContentResponse response = httpClient.GET("https://http2.akamai.com/"); // ContentResponse response = httpClient.GET("https://http2.akamai.com/");

View File

@ -206,7 +206,7 @@ public class MaxConcurrentStreamsTest extends AbstractTest
} }
}, promise, context); }, promise, context);
} }
}, null); });
QueuedThreadPool clientExecutor = new QueuedThreadPool(); QueuedThreadPool clientExecutor = new QueuedThreadPool();
clientExecutor.setName("client"); clientExecutor.setName("client");
client.setExecutor(clientExecutor); client.setExecutor(clientExecutor);

View File

@ -50,7 +50,7 @@ public class ClientConnector extends ContainerLifeCycle
private Executor executor; private Executor executor;
private Scheduler scheduler; private Scheduler scheduler;
private ByteBufferPool byteBufferPool; private ByteBufferPool byteBufferPool;
private SslContextFactory sslContextFactory; private SslContextFactory.Client sslContextFactory;
private SelectorManager selectorManager; private SelectorManager selectorManager;
private int selectors = 1; private int selectors = 1;
private boolean connectBlocking; private boolean connectBlocking;
@ -97,12 +97,12 @@ public class ClientConnector extends ContainerLifeCycle
this.byteBufferPool = byteBufferPool; this.byteBufferPool = byteBufferPool;
} }
public SslContextFactory getSslContextFactory() public SslContextFactory.Client getSslContextFactory()
{ {
return sslContextFactory; return sslContextFactory;
} }
public void setSslContextFactory(SslContextFactory sslContextFactory) public void setSslContextFactory(SslContextFactory.Client sslContextFactory)
{ {
if (isStarted()) if (isStarted())
throw new IllegalStateException(); throw new IllegalStateException();
@ -192,9 +192,9 @@ public class ClientConnector extends ContainerLifeCycle
removeBean(selectorManager); removeBean(selectorManager);
} }
protected SslContextFactory newSslContextFactory() protected SslContextFactory.Client newSslContextFactory()
{ {
SslContextFactory sslContextFactory = new SslContextFactory(false); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(false);
sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS"); sslContextFactory.setEndpointIdentificationAlgorithm("HTTPS");
return sslContextFactory; return sslContextFactory;
} }

View File

@ -295,8 +295,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
} }
catch (Throwable x) catch (Throwable x)
{ {
if (LOG.isDebugEnabled()) LOG.ignore(x);
LOG.debug(x);
return -1; return -1;
} }
} }
@ -309,8 +308,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable
} }
catch (Throwable x) catch (Throwable x)
{ {
if (LOG.isDebugEnabled()) LOG.ignore(x);
LOG.debug(x);
return -1; return -1;
} }
} }

View File

@ -389,9 +389,9 @@ abstract public class WriteFlusher
boolean progress = true; boolean progress = true;
while (progress && buffers != null) while (progress && buffers != null)
{ {
long before = remaining(buffers); long before = BufferUtil.remaining(buffers);
boolean flushed = _endPoint.flush(buffers); boolean flushed = _endPoint.flush(buffers);
long after = remaining(buffers); long after = BufferUtil.remaining(buffers);
long written = before - after; long written = before - after;
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
@ -441,16 +441,6 @@ abstract public class WriteFlusher
return buffers == null ? EMPTY_BUFFERS : buffers; 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 * Notify the flusher of a failure
* *

View File

@ -835,6 +835,12 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
LOG.debug("flush b[{}]={}", i++, BufferUtil.toDetailString(b)); 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; Boolean result = null;
try try
{ {
@ -866,7 +872,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
if (filled < 0) if (filled < 0)
throw new IOException("Broken pipe"); throw new IOException("Broken pipe");
} }
return result = false; return result = isEmpty;
default: default:
throw new IllegalStateException("Unexpected HandshakeStatus " + status); throw new IllegalStateException("Unexpected HandshakeStatus " + status);
@ -895,10 +901,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
_sslEngine.isOutboundDone()); _sslEngine.isOutboundDone());
// Was all the data consumed? // Was all the data consumed?
boolean allConsumed = true; isEmpty = BufferUtil.isEmpty(appOuts);
for (ByteBuffer b : appOuts)
if (BufferUtil.hasContent(b))
allConsumed = false;
// if we have net bytes, let's try to flush them // if we have net bytes, let's try to flush them
boolean flushed = true; boolean flushed = true;
@ -906,7 +909,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
flushed = getEndPoint().flush(_encryptedOutput); flushed = getEndPoint().flush(_encryptedOutput);
if (LOG.isDebugEnabled()) 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 // Now deal with the results returned from the wrap
Status wrap = wrapResult.getStatus(); Status wrap = wrapResult.getStatus();
@ -919,7 +922,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
if (!flushed) if (!flushed)
return result = false; return result = false;
getEndPoint().shutdownOutput(); getEndPoint().shutdownOutput();
if (allConsumed) if (isEmpty)
return result = true; return result = true;
throw new IOException("Broken pipe"); throw new IOException("Broken pipe");
} }
@ -936,15 +939,20 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
if (isRenegotiating() && !allowRenegotiate()) if (isRenegotiating() && !allowRenegotiate())
{ {
getEndPoint().shutdownOutput(); getEndPoint().shutdownOutput();
if (allConsumed && BufferUtil.isEmpty(_encryptedOutput)) if (isEmpty && BufferUtil.isEmpty(_encryptedOutput))
return result = true; return result = true;
throw new IOException("Broken pipe"); throw new IOException("Broken pipe");
} }
if (!flushed) if (!flushed)
return result = false; return result = false;
if (allConsumed)
return result = true; if (isEmpty)
{
if (wrapResult.getHandshakeStatus() != HandshakeStatus.NEED_WRAP ||
wrapResult.bytesProduced() == 0)
return result = true;
}
break; break;
default: default:
@ -1073,14 +1081,15 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
@Override @Override
public void doShutdownOutput() public void doShutdownOutput()
{ {
final EndPoint endp = getEndPoint();
try try
{ {
boolean close; boolean close;
boolean flush = false; boolean flush = false;
synchronized (_decryptedEndPoint) synchronized (_decryptedEndPoint)
{ {
boolean ishut = getEndPoint().isInputShutdown(); boolean ishut = endp.isInputShutdown();
boolean oshut = getEndPoint().isOutputShutdown(); boolean oshut = endp.isOutputShutdown();
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("shutdownOutput: {} oshut={}, ishut={} {}", SslConnection.this, oshut, ishut); LOG.debug("shutdownOutput: {} oshut={}, ishut={} {}", SslConnection.this, oshut, ishut);
@ -1097,16 +1106,28 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
} }
if (flush) 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) if (close)
getEndPoint().close(); endp.close();
else else
ensureFillInterested(); ensureFillInterested();
} }
catch (Throwable x) catch (Throwable x)
{ {
LOG.ignore(x); LOG.ignore(x);
getEndPoint().close(); endp.close();
} }
} }

View File

@ -625,24 +625,23 @@ public class SocketChannelEndPointTest
public static class SslScenario implements Scenario public static class SslScenario implements Scenario
{ {
private final NormalScenario _normalScenario; private final NormalScenario _normalScenario;
private final SslContextFactory __sslCtxFactory = new SslContextFactory(); private final SslContextFactory _sslCtxFactory = new SslContextFactory.Server();
private final ByteBufferPool __byteBufferPool = new MappedByteBufferPool(); private final ByteBufferPool _byteBufferPool = new MappedByteBufferPool();
public SslScenario(NormalScenario normalScenario) throws Exception public SslScenario(NormalScenario normalScenario) throws Exception
{ {
_normalScenario = normalScenario; _normalScenario = normalScenario;
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
__sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); _sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath());
__sslCtxFactory.setKeyStorePassword("storepwd"); _sslCtxFactory.setKeyStorePassword("storepwd");
__sslCtxFactory.setKeyManagerPassword("keypwd"); _sslCtxFactory.setKeyManagerPassword("keypwd");
__sslCtxFactory.setEndpointIdentificationAlgorithm(""); _sslCtxFactory.start();
__sslCtxFactory.start();
} }
@Override @Override
public Socket newClient(ServerSocketChannel connector) throws IOException public Socket newClient(ServerSocketChannel connector) throws IOException
{ {
SSLSocket socket = __sslCtxFactory.newSslSocket(); SSLSocket socket = _sslCtxFactory.newSslSocket();
socket.connect(connector.socket().getLocalSocketAddress()); socket.connect(connector.socket().getLocalSocketAddress());
return socket; return socket;
} }
@ -650,11 +649,11 @@ public class SocketChannelEndPointTest
@Override @Override
public Connection newConnection(SelectableChannel channel, EndPoint endpoint, Executor executor, AtomicInteger blockAt, AtomicInteger writeCount) public Connection newConnection(SelectableChannel channel, EndPoint endpoint, Executor executor, AtomicInteger blockAt, AtomicInteger writeCount)
{ {
SSLEngine engine = __sslCtxFactory.newSSLEngine(); SSLEngine engine = _sslCtxFactory.newSSLEngine();
engine.setUseClientMode(false); engine.setUseClientMode(false);
SslConnection sslConnection = new SslConnection(__byteBufferPool, executor, endpoint, engine); SslConnection sslConnection = new SslConnection(_byteBufferPool, executor, endpoint, engine);
sslConnection.setRenegotiationAllowed(__sslCtxFactory.isRenegotiationAllowed()); sslConnection.setRenegotiationAllowed(_sslCtxFactory.isRenegotiationAllowed());
sslConnection.setRenegotiationLimit(__sslCtxFactory.getRenegotiationLimit()); sslConnection.setRenegotiationLimit(_sslCtxFactory.getRenegotiationLimit());
Connection appConnection = _normalScenario.newConnection(channel, sslConnection.getDecryptedEndPoint(), executor, blockAt, writeCount); Connection appConnection = _normalScenario.newConnection(channel, sslConnection.getDecryptedEndPoint(), executor, blockAt, writeCount);
sslConnection.getDecryptedEndPoint().setConnection(appConnection); sslConnection.getDecryptedEndPoint().setConnection(appConnection);
return sslConnection; return sslConnection;

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.Socket; import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel; import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey; import java.nio.channels.SelectionKey;
@ -31,6 +32,7 @@ import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.SSLEngine; 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.BeforeEach;
import org.junit.jupiter.api.Test; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
@ -60,9 +64,11 @@ public class SslConnectionTest
private static final int TIMEOUT = 1000000; private static final int TIMEOUT = 1000000;
private static ByteBufferPool __byteBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); 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; protected volatile EndPoint _lastEndp;
private volatile boolean _testFill=true; private volatile boolean _testFill=true;
private volatile boolean _onXWriteThenShutdown=false;
private volatile FutureCallback _writeCallback; private volatile FutureCallback _writeCallback;
protected ServerSocketChannel _connector; protected ServerSocketChannel _connector;
final AtomicInteger _dispatches = new AtomicInteger(); final AtomicInteger _dispatches = new AtomicInteger();
@ -92,7 +98,6 @@ public class SslConnectionTest
return sslConnection; return sslConnection;
} }
@Override @Override
protected EndPoint newEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey selectionKey) 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 __startBlocking = new AtomicInteger();
static final AtomicInteger __blockFor = new AtomicInteger(); static final AtomicInteger __blockFor = new AtomicInteger();
static final AtomicBoolean __onIncompleteFlush = new AtomicBoolean();
private static class TestEP extends SocketChannelEndPoint private static class TestEP extends SocketChannelEndPoint
{ {
public TestEP(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler) public TestEP(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler)
@ -115,13 +121,14 @@ public class SslConnectionTest
@Override @Override
protected void onIncompleteFlush() protected void onIncompleteFlush()
{ {
super.onIncompleteFlush(); __onIncompleteFlush.set(true);
} }
@Override @Override
public boolean flush(ByteBuffer... buffers) throws IOException public boolean flush(ByteBuffer... buffers) throws IOException
{ {
__onIncompleteFlush.set(false);
if (__startBlocking.get()==0 || __startBlocking.decrementAndGet()==0) if (__startBlocking.get()==0 || __startBlocking.decrementAndGet()==0)
{ {
if (__blockFor.get()>0 && __blockFor.getAndDecrement()>0) if (__blockFor.get()>0 && __blockFor.getAndDecrement()>0)
@ -133,7 +140,6 @@ public class SslConnectionTest
} }
} }
@BeforeEach @BeforeEach
public void initSSL() throws Exception public void initSSL() throws Exception
{ {
@ -143,7 +149,6 @@ public class SslConnectionTest
_sslCtxFactory.setKeyManagerPassword("keypwd"); _sslCtxFactory.setKeyManagerPassword("keypwd");
_sslCtxFactory.setRenegotiationAllowed(true); _sslCtxFactory.setRenegotiationAllowed(true);
_sslCtxFactory.setRenegotiationLimit(-1); _sslCtxFactory.setRenegotiationLimit(-1);
_sslCtxFactory.setEndpointIdentificationAlgorithm(null);
startManager(); startManager();
} }
@ -227,20 +232,23 @@ public class SslConnectionTest
filled=endp.fill(_in); filled=endp.fill(_in);
} }
boolean shutdown = _onXWriteThenShutdown && BufferUtil.toString(_in).contains("X");
// Write everything // Write everything
int l=_in.remaining(); int l=_in.remaining();
if (l>0) if (l>0)
{ {
FutureCallback blockingWrite= new FutureCallback(); FutureCallback blockingWrite= new FutureCallback();
endp.write(blockingWrite,_in); endp.write(blockingWrite,_in);
blockingWrite.get(); blockingWrite.get();
if (shutdown)
endp.shutdownOutput();
} }
// are we done? // are we done?
if (endp.isInputShutdown()) if (endp.isInputShutdown() || shutdown)
{
endp.shutdownOutput(); endp.shutdownOutput();
}
} }
} }
catch(InterruptedException|EofException e) catch(InterruptedException|EofException e)
@ -426,7 +434,7 @@ public class SslConnectionTest
public void testBlockedWrite() throws Exception public void testBlockedWrite() throws Exception
{ {
startSSL(); startSSL();
try (Socket client = newClient()) try (SSLSocket client = newClient())
{ {
client.setSoTimeout(5000); client.setSoTimeout(5000);
try (SocketChannel server = _connector.accept()) try (SocketChannel server = _connector.accept())
@ -434,21 +442,78 @@ public class SslConnectionTest
server.configureBlocking(false); server.configureBlocking(false);
_manager.accept(server); _manager.accept(server);
__startBlocking.set(5);
__blockFor.set(3);
client.getOutputStream().write("Hello".getBytes(StandardCharsets.UTF_8)); client.getOutputStream().write("Hello".getBytes(StandardCharsets.UTF_8));
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int len = client.getInputStream().read(buffer); int len = client.getInputStream().read(buffer);
assertEquals(5, len);
assertEquals("Hello", new String(buffer, 0, len, StandardCharsets.UTF_8)); assertEquals("Hello", new String(buffer, 0, len, StandardCharsets.UTF_8));
__startBlocking.set(0);
__blockFor.set(2);
_dispatches.set(0); _dispatches.set(0);
client.getOutputStream().write("World".getBytes(StandardCharsets.UTF_8)); client.getOutputStream().write("World".getBytes(StandardCharsets.UTF_8));
len = 5;
while (len > 0) try
len -= client.getInputStream().read(buffer); {
assertEquals(0, len); 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(); String line = in.readLine();
if (line == null) if (line == null)
break; break;
// System.err.println(line);
count.countDown(); count.countDown();
} }
} }
@ -491,7 +555,6 @@ public class SslConnectionTest
for (int i = 0; i < LINES; i++) for (int i = 0; i < LINES; i++)
{ {
client.getOutputStream().write(("HelloWorld " + i + "\n").getBytes(StandardCharsets.UTF_8)); client.getOutputStream().write(("HelloWorld " + i + "\n").getBytes(StandardCharsets.UTF_8));
// System.err.println("wrote");
if (i % 1000 == 0) if (i % 1000 == 0)
{ {
client.getOutputStream().flush(); client.getOutputStream().flush();

View File

@ -18,10 +18,6 @@
package org.eclipse.jetty.io; 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.io.File;
import java.nio.ByteBuffer; 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.BufferUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnJre; import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE; 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 public class SslEngineBehaviorTest
{ {
private static SslContextFactory sslCtxFactory; private static SslContextFactory sslCtxFactory;
@ -45,12 +44,11 @@ public class SslEngineBehaviorTest
@BeforeAll @BeforeAll
public static void startSsl() throws Exception public static void startSsl() throws Exception
{ {
sslCtxFactory = new SslContextFactory(); sslCtxFactory = new SslContextFactory.Server();
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath());
sslCtxFactory.setKeyStorePassword("storepwd"); sslCtxFactory.setKeyStorePassword("storepwd");
sslCtxFactory.setKeyManagerPassword("keypwd"); sslCtxFactory.setKeyManagerPassword("keypwd");
sslCtxFactory.setEndpointIdentificationAlgorithm("");
sslCtxFactory.start(); sslCtxFactory.start();
} }

View File

@ -18,10 +18,6 @@
package org.eclipse.jetty.jmx; 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.ConnectException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; 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.Disabled;
import org.junit.jupiter.api.Test; 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 * Running the tests of this class in the same JVM results often in
* <pre> * <pre>
@ -227,7 +227,7 @@ public class ConnectorServerTest
@Test @Test
public void testJMXOverTLS() throws Exception public void testJMXOverTLS() throws Exception
{ {
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory sslContextFactory = new SslContextFactory.Server();
String keyStorePath = MavenTestingUtils.getTestResourcePath("keystore.jks").toString(); String keyStorePath = MavenTestingUtils.getTestResourcePath("keystore.jks").toString();
String keyStorePassword = "storepwd"; String keyStorePassword = "storepwd";
sslContextFactory.setKeyStorePath(keyStorePath); sslContextFactory.setKeyStorePath(keyStorePath);

View File

@ -24,7 +24,7 @@
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>1.7.9</version> <version>${slf4j.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -29,7 +29,7 @@
<!-- ============================================================= --> <!-- ============================================================= -->
<!-- Create a TLS (SSL) Context Factory for later reuse --> <!-- Create a TLS (SSL) Context Factory for later reuse -->
<!-- ============================================================= --> <!-- ============================================================= -->
<New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"> <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
<Set name="Provider"><SystemProperty name="jetty.sslContext.provider"/></Set> <Set name="Provider"><SystemProperty name="jetty.sslContext.provider"/></Set>
<Set name="KeyStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.sslContext.keyStorePath" default="etc/keystore"/></Set> <Set name="KeyStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.sslContext.keyStorePath" default="etc/keystore"/></Set>
<Set name="KeyStorePassword"><Property name="jetty.sslContext.keyStorePassword" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set> <Set name="KeyStorePassword"><Property name="jetty.sslContext.keyStorePassword" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; 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.JavaVersion;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -137,8 +138,8 @@ public class TestJettyOSGiBootHTTP2Conscrypt
Path path = Paths.get("src", "test", "config"); Path path = Paths.get("src", "test", "config");
File keys = path.resolve("etc").resolve("keystore").toFile(); File keys = path.resolve("etc").resolve("keystore").toFile();
HTTP2Client http2Client = new HTTP2Client(); ClientConnector clientConnector = new ClientConnector();
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setTrustStorePath(keys.getAbsolutePath()); sslContextFactory.setTrustStorePath(keys.getAbsolutePath());
sslContextFactory.setKeyStorePath(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. // Conscrypt enables TLSv1.3 by default but it's not supported in Java 8.
sslContextFactory.addExcludeProtocols("TLSv1.3"); 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(); Executor executor = new QueuedThreadPool();
httpClient.setExecutor(executor); httpClient.setExecutor(executor);

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; 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.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.Test; import org.junit.Test;
@ -131,15 +132,16 @@ public class TestJettyOSGiBootHTTP2JDK9
Path path = Paths.get("src", "test", "config"); Path path = Paths.get("src", "test", "config");
File keys = path.resolve("etc").resolve("keystore").toFile(); File keys = path.resolve("etc").resolve("keystore").toFile();
//set up client to do http2 ClientConnector clientConnector = new ClientConnector();
http2Client = new HTTP2Client(); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setKeyManagerPassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setTrustStorePath(keys.getAbsolutePath()); sslContextFactory.setTrustStorePath(keys.getAbsolutePath());
sslContextFactory.setKeyStorePath(keys.getAbsolutePath()); sslContextFactory.setKeyStorePath(keys.getAbsolutePath());
sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); sslContextFactory.setTrustStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
sslContextFactory.setEndpointIdentificationAlgorithm(null); 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(); Executor executor = new QueuedThreadPool();
httpClient.setExecutor(executor); httpClient.setExecutor(executor);
httpClient.start(); httpClient.start();

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; 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.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
@ -56,7 +59,6 @@ import static org.ops4j.pax.exam.CoreOptions.systemProperty;
*/ */
public class TestOSGiUtil public class TestOSGiUtil
{ {
public static final String BUNDLE_DEBUG = "bundle.debug"; public static final String BUNDLE_DEBUG = "bundle.debug";
public static List<Option> configureJettyHomeAndPort(boolean ssl,String jettySelectorFileName) public static List<Option> configureJettyHomeAndPort(boolean ssl,String jettySelectorFileName)
@ -276,10 +278,10 @@ public class TestOSGiUtil
return bundleContext.getAllServiceReferences(service, null); return bundleContext.getAllServiceReferences(service, null);
} }
protected static SslContextFactory newSslContextFactory() protected static SslContextFactory.Client newClientSslContextFactory()
{ {
SslContextFactory sslContextFactory = new SslContextFactory(true); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(true);
sslContextFactory.setEndpointIdentificationAlgorithm(""); sslContextFactory.setEndpointIdentificationAlgorithm(null);
return sslContextFactory; return sslContextFactory;
} }
@ -330,7 +332,10 @@ public class TestOSGiUtil
}, null, null); }, null, null);
// now test the servlet // now test the servlet
HttpClient client = protocol.equals("https") ? new HttpClient(newSslContextFactory()) : new HttpClient(); ClientConnector clientConnector = new ClientConnector();
clientConnector.setSelectors(1);
clientConnector.setSslContextFactory(newClientSslContextFactory());
HttpClient client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
try try
{ {
client.start(); client.start();

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.proxy;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.URI; import java.net.URI;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -84,21 +83,17 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
public abstract class AbstractProxyServlet extends HttpServlet public abstract class AbstractProxyServlet extends HttpServlet
{ {
protected static final String CLIENT_REQUEST_ATTRIBUTE = "org.eclipse.jetty.proxy.clientRequest"; protected static final String CLIENT_REQUEST_ATTRIBUTE = "org.eclipse.jetty.proxy.clientRequest";
protected static final Set<String> HOP_HEADERS; protected static final Set<String> HOP_HEADERS = Set.of(
static "connection",
{ "keep-alive",
Set<String> hopHeaders = new HashSet<>(); "proxy-authorization",
hopHeaders.add("connection"); "proxy-authenticate",
hopHeaders.add("keep-alive"); "proxy-connection",
hopHeaders.add("proxy-authorization"); "transfer-encoding",
hopHeaders.add("proxy-authenticate"); "te",
hopHeaders.add("proxy-connection"); "trailer",
hopHeaders.add("transfer-encoding"); "upgrade"
hopHeaders.add("te"); );
hopHeaders.add("trailer");
hopHeaders.add("upgrade");
HOP_HEADERS = Collections.unmodifiableSet(hopHeaders);
}
private final Set<String> _whiteList = new HashSet<>(); private final Set<String> _whiteList = new HashSet<>();
private final Set<String> _blackList = new HashSet<>(); private final Set<String> _blackList = new HashSet<>();
@ -353,11 +348,11 @@ public abstract class AbstractProxyServlet extends HttpServlet
*/ */
protected HttpClient newHttpClient() protected HttpClient newHttpClient()
{ {
int selectors = Math.max(1,ProcessorUtils.availableProcessors()/2); int selectors = Math.max(1, ProcessorUtils.availableProcessors() / 2);
String value = getServletConfig().getInitParameter("selectors"); String value = getServletConfig().getInitParameter("selectors");
if (value != null) if (value != null)
selectors = Integer.parseInt(value); selectors = Integer.parseInt(value);
return new HttpClient(new HttpClientTransportOverHTTP(selectors),null); return new HttpClient(new HttpClientTransportOverHTTP(selectors));
} }
protected HttpClient getHttpClient() protected HttpClient getHttpClient()

View File

@ -48,12 +48,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest public class ConnectHandlerSSLTest extends AbstractConnectHandlerTest
{ {
private SslContextFactory sslContextFactory; private SslContextFactory.Server sslContextFactory;
@BeforeEach @BeforeEach
public void prepare() throws Exception public void prepare() throws Exception
{ {
sslContextFactory = new SslContextFactory(); sslContextFactory = new SslContextFactory.Server();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
sslContextFactory.setKeyStorePath(keyStorePath); sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");

View File

@ -47,6 +47,7 @@ import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -88,6 +89,7 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
} }
@Test @Test
@Tag("ipv6")
public void testCONNECTwithIPv6() throws Exception public void testCONNECTwithIPv6() throws Exception
{ {
String hostPort = "[::1]:" + serverConnector.getLocalPort(); String hostPort = "[::1]:" + serverConnector.getLocalPort();

View File

@ -25,9 +25,11 @@ import java.util.stream.Stream;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.HttpProxy;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.AbstractConnectionFactory; import org.eclipse.jetty.server.AbstractConnectionFactory;
@ -60,9 +62,9 @@ public class ForwardProxyServerTest
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
// no server SSL // no server SSL
SslContextFactory scenario1 = null; SslContextFactory.Server scenario1 = null;
// basic server SSL // basic server SSL
SslContextFactory scenario2 = new SslContextFactory(); SslContextFactory.Server scenario2 = new SslContextFactory.Server();
scenario2.setKeyStorePath(keyStorePath); scenario2.setKeyStorePath(keyStorePath);
scenario2.setKeyStorePassword("storepwd"); scenario2.setKeyStorePassword("storepwd");
scenario2.setKeyManagerPassword("keypwd"); scenario2.setKeyManagerPassword("keypwd");
@ -71,13 +73,13 @@ public class ForwardProxyServerTest
return Stream.of(scenario1, scenario2).map(Arguments::of); return Stream.of(scenario1, scenario2).map(Arguments::of);
} }
private SslContextFactory serverSslContextFactory; private SslContextFactory.Server serverSslContextFactory;
private Server server; private Server server;
private ServerConnector serverConnector; private ServerConnector serverConnector;
private Server proxy; private Server proxy;
private ServerConnector proxyConnector; private ServerConnector proxyConnector;
public void init(SslContextFactory scenario) public void init(SslContextFactory.Server scenario)
{ {
serverSslContextFactory = scenario; serverSslContextFactory = scenario;
} }
@ -143,7 +145,7 @@ public class ForwardProxyServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testRequestTarget(SslContextFactory scenario) throws Exception public void testRequestTarget(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
@ -202,14 +204,16 @@ public class ForwardProxyServerTest
}); });
startProxy(); startProxy();
ClientConnector clientConnector = new ClientConnector();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory clientSsl = new SslContextFactory(); SslContextFactory.Client clientSsl = new SslContextFactory.Client();
clientSsl.setKeyStorePath(keyStorePath); clientSsl.setKeyStorePath(keyStorePath);
clientSsl.setKeyStorePassword("storepwd"); clientSsl.setKeyStorePassword("storepwd");
clientSsl.setKeyManagerPassword("keypwd"); clientSsl.setKeyManagerPassword("keypwd");
clientSsl.setEndpointIdentificationAlgorithm(null); clientSsl.setEndpointIdentificationAlgorithm(null);
clientConnector.setSslContextFactory(clientSsl);
HttpClient httpClient = new HttpClient(clientSsl); HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();

View File

@ -40,6 +40,7 @@ import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.Connection; import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.client.util.BasicAuthentication; import org.eclipse.jetty.client.util.BasicAuthentication;
import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.client.util.StringContentProvider;
@ -48,6 +49,7 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
@ -80,9 +82,9 @@ public class ForwardProxyTLSServerTest
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
// no server SSL // no server SSL
SslContextFactory scenario1 = null; SslContextFactory.Server scenario1 = null;
// basic server SSL // basic server SSL
SslContextFactory scenario2 = new SslContextFactory(); SslContextFactory.Server scenario2 = new SslContextFactory.Server();
scenario2.setKeyStorePath(keyStorePath); scenario2.setKeyStorePath(keyStorePath);
scenario2.setKeyStorePassword("storepwd"); scenario2.setKeyStorePassword("storepwd");
scenario2.setKeyManagerPassword("keypwd"); scenario2.setKeyManagerPassword("keypwd");
@ -91,13 +93,13 @@ public class ForwardProxyTLSServerTest
return Stream.of(scenario1, scenario2).map(Arguments::of); return Stream.of(scenario1, scenario2).map(Arguments::of);
} }
private SslContextFactory proxySslContextFactory; private SslContextFactory.Server proxySslContextFactory;
private Server server; private Server server;
private ServerConnector serverConnector; private ServerConnector serverConnector;
private Server proxy; private Server proxy;
private ServerConnector proxyConnector; private ServerConnector proxyConnector;
public void init(SslContextFactory scenario) public void init(SslContextFactory.Server scenario)
{ {
proxySslContextFactory = scenario; proxySslContextFactory = scenario;
} }
@ -137,22 +139,35 @@ public class ForwardProxyTLSServerTest
return new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxySslContextFactory != null); return new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxySslContextFactory != null);
} }
private static SslContextFactory newServerSslContextFactory() private HttpClient newHttpClient()
{
ClientConnector clientConnector = new ClientConnector();
clientConnector.setSelectors(1);
clientConnector.setSslContextFactory(newClientSslContextFactory());
return new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
}
private static SslContextFactory.Server newServerSslContextFactory()
{
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
configureSslContextFactory(sslContextFactory);
return sslContextFactory;
}
private static SslContextFactory.Client newClientSslContextFactory()
{
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
configureSslContextFactory(sslContextFactory);
sslContextFactory.setEndpointIdentificationAlgorithm(null);
return sslContextFactory;
}
private static void configureSslContextFactory(SslContextFactory sslContextFactory)
{ {
SslContextFactory sslContextFactory = new SslContextFactory();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
sslContextFactory.setKeyStorePath(keyStorePath); sslContextFactory.setKeyStorePath(keyStorePath);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");
return sslContextFactory;
}
private static SslContextFactory newClientSslContextFactory()
{
SslContextFactory sslContextFactory = newServerSslContextFactory();
sslContextFactory.setEndpointIdentificationAlgorithm(null);
return sslContextFactory;
} }
@AfterEach @AfterEach
@ -182,13 +197,13 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testOneExchange(SslContextFactory scenario) throws Exception public void testOneExchange(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy();
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();
@ -218,13 +233,13 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testTwoExchanges(SslContextFactory scenario) throws Exception public void testTwoExchanges(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy();
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();
@ -265,20 +280,20 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testTwoConcurrentExchanges(SslContextFactory scenario) throws Exception public void testTwoConcurrentExchanges(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(); startProxy();
final HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();
try try
{ {
final AtomicReference<Connection> connection = new AtomicReference<>(); AtomicReference<Connection> connection = new AtomicReference<>();
final CountDownLatch connectionLatch = new CountDownLatch(1); CountDownLatch connectionLatch = new CountDownLatch(1);
String content1 = "BODY"; String content1 = "BODY";
ContentResponse response1 = httpClient.newRequest("localhost", serverConnector.getLocalPort()) ContentResponse response1 = httpClient.newRequest("localhost", serverConnector.getLocalPort())
.scheme(HttpScheme.HTTPS.asString()) .scheme(HttpScheme.HTTPS.asString())
@ -287,7 +302,7 @@ public class ForwardProxyTLSServerTest
.onRequestCommit(request -> .onRequestCommit(request ->
{ {
Destination destination = httpClient.getDestination(HttpScheme.HTTPS.asString(), "localhost", serverConnector.getLocalPort()); Destination destination = httpClient.getDestination(HttpScheme.HTTPS.asString(), "localhost", serverConnector.getLocalPort());
destination.newConnection(new Promise.Adapter<Connection>() destination.newConnection(new Promise.Adapter<>()
{ {
@Override @Override
public void succeeded(Connection result) public void succeeded(Connection result)
@ -332,7 +347,7 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testShortIdleTimeoutOverriddenByRequest(SslContextFactory scenario) throws Exception public void testShortIdleTimeoutOverriddenByRequest(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
// Short idle timeout for HttpClient. // Short idle timeout for HttpClient.
@ -357,7 +372,7 @@ public class ForwardProxyTLSServerTest
} }
}); });
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
// Short idle timeout for HttpClient. // Short idle timeout for HttpClient.
httpClient.setIdleTimeout(idleTimeout); httpClient.setIdleTimeout(idleTimeout);
@ -388,7 +403,7 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyDown(SslContextFactory scenario) throws Exception public void testProxyDown(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
@ -396,7 +411,7 @@ public class ForwardProxyTLSServerTest
int proxyPort = proxyConnector.getLocalPort(); int proxyPort = proxyConnector.getLocalPort();
stopProxy(); stopProxy();
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null)); httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(new Origin.Address("localhost", proxyPort), proxySslContextFactory != null));
httpClient.start(); httpClient.start();
@ -416,7 +431,7 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testServerDown(SslContextFactory scenario) throws Exception public void testServerDown(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
@ -424,7 +439,7 @@ public class ForwardProxyTLSServerTest
stopServer(); stopServer();
startProxy(); startProxy();
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();
@ -443,7 +458,7 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyClosesConnection(SslContextFactory scenario) throws Exception public void testProxyClosesConnection(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
@ -456,26 +471,25 @@ public class ForwardProxyTLSServerTest
} }
}); });
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy()); httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
httpClient.start(); httpClient.start();
assertThrows(ExecutionException.class, ()->{ assertThrows(ExecutionException.class, () ->
httpClient.newRequest("localhost", serverConnector.getLocalPort()) httpClient.newRequest("localhost", serverConnector.getLocalPort())
.scheme(HttpScheme.HTTPS.asString()) .scheme(HttpScheme.HTTPS.asString())
.timeout(5, TimeUnit.SECONDS) .timeout(5, TimeUnit.SECONDS)
.send(); .send());
});
httpClient.stop(); httpClient.stop();
} }
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyAuthentication(SslContextFactory scenario) throws Exception public void testProxyAuthentication(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
final String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(realm, new ConnectHandler()
{ {
@Override @Override
@ -496,10 +510,10 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyAuthenticationWithResponseContent(SslContextFactory scenario) throws Exception public void testProxyAuthenticationWithResponseContent(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
final String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(realm, new ConnectHandler()
{ {
@Override @Override
@ -521,10 +535,10 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyAuthenticationWithIncludedAddressWithResponseContent(SslContextFactory scenario) throws Exception public void testProxyAuthenticationWithIncludedAddressWithResponseContent(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
final String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(realm, new ConnectHandler()
{ {
@Override @Override
@ -546,16 +560,16 @@ public class ForwardProxyTLSServerTest
@ParameterizedTest @ParameterizedTest
@MethodSource("scenarios") @MethodSource("scenarios")
public void testProxyAuthenticationClosesConnection(SslContextFactory scenario) throws Exception public void testProxyAuthenticationClosesConnection(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
final String realm = "test-realm"; String realm = "test-realm";
testProxyAuthentication(realm, new ConnectHandler() testProxyAuthentication(realm, new ConnectHandler()
{ {
@Override @Override
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address)
{ {
final String header = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.toString()); String header = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.toString());
if (header == null || !header.startsWith("Basic ")) if (header == null || !header.startsWith("Basic "))
{ {
response.setHeader(HttpHeader.PROXY_AUTHENTICATE.toString(), "Basic realm=\"" + realm + "\""); response.setHeader(HttpHeader.PROXY_AUTHENTICATE.toString(), "Basic realm=\"" + realm + "\"");
@ -580,7 +594,7 @@ public class ForwardProxyTLSServerTest
startTLSServer(new ServerHandler()); startTLSServer(new ServerHandler());
startProxy(connectHandler); startProxy(connectHandler);
HttpClient httpClient = new HttpClient(newClientSslContextFactory()); HttpClient httpClient = newHttpClient();
HttpProxy httpProxy = newHttpProxy(); HttpProxy httpProxy = newHttpProxy();
if (includeAddress) if (includeAddress)
httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort()); httpProxy.getIncludedAddresses().add("localhost:" + serverConnector.getLocalPort());
@ -614,7 +628,7 @@ public class ForwardProxyTLSServerTest
@MethodSource("scenarios") @MethodSource("scenarios")
@Tag("Unstable") @Tag("Unstable")
@Disabled("External Proxy Server no longer stable enough for testing") @Disabled("External Proxy Server no longer stable enough for testing")
public void testExternalProxy(SslContextFactory scenario) throws Exception public void testExternalProxy(SslContextFactory.Server scenario) throws Exception
{ {
init(scenario); init(scenario);
// Free proxy server obtained from http://hidemyass.com/proxy-list/ // Free proxy server obtained from http://hidemyass.com/proxy-list/
@ -629,10 +643,7 @@ public class ForwardProxyTLSServerTest
assumeTrue(false, "Environment not able to connect to proxy service"); assumeTrue(false, "Environment not able to connect to proxy service");
} }
SslContextFactory sslContextFactory = new SslContextFactory(); HttpClient httpClient = newHttpClient();
sslContextFactory.start();
HttpClient httpClient = new HttpClient(newClientSslContextFactory());
httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort)); httpClient.getProxyConfiguration().getProxies().add(new HttpProxy(proxyHost, proxyPort));
httpClient.start(); httpClient.start();

View File

@ -10,7 +10,7 @@
https://www.eclipse.org/jetty/documentation/current/configuring-ssl.html#configuring-sslcontextfactory-cipherSuites https://www.eclipse.org/jetty/documentation/current/configuring-ssl.html#configuring-sslcontextfactory-cipherSuites
--> -->
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory"> <Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
<Set name="Provider"><Property name="jetty.sslContext.provider"/></Set> <Set name="Provider"><Property name="jetty.sslContext.provider"/></Set>
<Set name="KeyStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.sslContext.keyStorePath" default="etc/keystore"/></Set> <Set name="KeyStorePath"><Property name="jetty.base" default="." />/<Property name="jetty.sslContext.keyStorePath" default="etc/keystore"/></Set>
<Set name="KeyStorePassword"><Property name="jetty.sslContext.keyStorePassword" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set> <Set name="KeyStorePassword"><Property name="jetty.sslContext.keyStorePassword" default="OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"/></Set>

View File

@ -111,7 +111,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
return String.format("%s@%x%s",this.getClass().getSimpleName(),hashCode(),getProtocols()); return String.format("%s@%x%s",this.getClass().getSimpleName(),hashCode(),getProtocols());
} }
public static ConnectionFactory[] getFactories(SslContextFactory sslContextFactory, ConnectionFactory... factories) public static ConnectionFactory[] getFactories(SslContextFactory.Server sslContextFactory, ConnectionFactory... factories)
{ {
factories=ArrayUtil.removeNulls(factories); factories=ArrayUtil.removeNulls(factories);

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
@ -63,7 +62,7 @@ public class LocalConnector extends AbstractConnector
this(server, null, null, null, -1, new HttpConnectionFactory()); this(server, null, null, null, -1, new HttpConnectionFactory());
} }
public LocalConnector(Server server, SslContextFactory sslContextFactory) public LocalConnector(Server server, SslContextFactory.Server sslContextFactory)
{ {
this(server, null, null, null, -1,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); this(server, null, null, null, -1,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
} }
@ -73,7 +72,7 @@ public class LocalConnector extends AbstractConnector
this(server, null, null, null, -1, connectionFactory); this(server, null, null, null, -1, connectionFactory);
} }
public LocalConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory sslContextFactory) public LocalConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory.Server sslContextFactory)
{ {
this(server, null, null, null, -1, AbstractConnectionFactory.getFactories(sslContextFactory,connectionFactory)); this(server, null, null, null, -1, AbstractConnectionFactory.getFactories(sslContextFactory,connectionFactory));
} }
@ -113,7 +112,7 @@ public class LocalConnector extends AbstractConnector
} }
@Override @Override
protected void accept(int acceptorID) throws IOException, InterruptedException protected void accept(int acceptorID) throws InterruptedException
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("accepting {}", acceptorID); LOG.debug("accepting {}", acceptorID);
@ -401,7 +400,7 @@ public class LocalConnector extends AbstractConnector
HttpParser parser = new HttpParser(handler); HttpParser parser = new HttpParser(handler);
parser.setHeadResponse(head); parser.setHeadResponse(head);
try(ByteArrayOutputStream2 bout = new ByteArrayOutputStream2();) try(ByteArrayOutputStream2 bout = new ByteArrayOutputStream2())
{ {
loop: while(true) loop: while(true)
{ {
@ -416,7 +415,7 @@ public class LocalConnector extends AbstractConnector
{ {
parser.atEOF(); parser.atEOF();
parser.parseNext(BufferUtil.EMPTY_BUFFER); parser.parseNext(BufferUtil.EMPTY_BUFFER);
break loop; break;
} }
} }

View File

@ -47,7 +47,7 @@ public class NetworkTrafficServerConnector extends ServerConnector
this(server, null, null, null, 0, 0, new HttpConnectionFactory()); this(server, null, null, null, 0, 0, new HttpConnectionFactory());
} }
public NetworkTrafficServerConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory sslContextFactory) public NetworkTrafficServerConnector(Server server, ConnectionFactory connectionFactory, SslContextFactory.Server sslContextFactory)
{ {
super(server, sslContextFactory, connectionFactory); super(server, sslContextFactory, connectionFactory);
} }
@ -62,7 +62,7 @@ public class NetworkTrafficServerConnector extends ServerConnector
super(server, executor, scheduler, pool, acceptors, selectors, factories); super(server, executor, scheduler, pool, acceptors, selectors, factories);
} }
public NetworkTrafficServerConnector(Server server, SslContextFactory sslContextFactory) public NetworkTrafficServerConnector(Server server, SslContextFactory.Server sslContextFactory)
{ {
super(server, sslContextFactory); super(server, sslContextFactory);
} }

View File

@ -150,7 +150,7 @@ public class ServerConnector extends AbstractNetworkConnector
*/ */
public ServerConnector( public ServerConnector(
@Name("server") Server server, @Name("server") Server server,
@Name("sslContextFactory") SslContextFactory sslContextFactory) @Name("sslContextFactory") SslContextFactory.Server sslContextFactory)
{ {
this(server,null,null,null,-1,-1,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); this(server,null,null,null,-1,-1,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
} }
@ -170,7 +170,7 @@ public class ServerConnector extends AbstractNetworkConnector
@Name("server") Server server, @Name("server") Server server,
@Name("acceptors") int acceptors, @Name("acceptors") int acceptors,
@Name("selectors") int selectors, @Name("selectors") int selectors,
@Name("sslContextFactory") SslContextFactory sslContextFactory) @Name("sslContextFactory") SslContextFactory.Server sslContextFactory)
{ {
this(server,null,null,null,acceptors,selectors,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); this(server,null,null,null,acceptors,selectors,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
} }
@ -183,7 +183,7 @@ public class ServerConnector extends AbstractNetworkConnector
*/ */
public ServerConnector( public ServerConnector(
@Name("server") Server server, @Name("server") Server server,
@Name("sslContextFactory") SslContextFactory sslContextFactory, @Name("sslContextFactory") SslContextFactory.Server sslContextFactory,
@Name("factories") ConnectionFactory... factories) @Name("factories") ConnectionFactory... factories)
{ {
this(server, null, null, null, -1, -1, AbstractConnectionFactory.getFactories(sslContextFactory, factories)); this(server, null, null, null, -1, -1, AbstractConnectionFactory.getFactories(sslContextFactory, factories));

View File

@ -35,7 +35,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslConnectionFactory extends AbstractConnectionFactory public class SslConnectionFactory extends AbstractConnectionFactory
{ {
private final SslContextFactory _sslContextFactory; private final SslContextFactory.Server _sslContextFactory;
private final String _nextProtocol; private final String _nextProtocol;
private boolean _directBuffersForEncryption = false; private boolean _directBuffersForEncryption = false;
private boolean _directBuffersForDecryption = false; private boolean _directBuffersForDecryption = false;
@ -50,15 +50,15 @@ public class SslConnectionFactory extends AbstractConnectionFactory
this(null,nextProtocol); this(null,nextProtocol);
} }
public SslConnectionFactory(@Name("sslContextFactory") SslContextFactory factory, @Name("next") String nextProtocol) public SslConnectionFactory(@Name("sslContextFactory") SslContextFactory.Server factory, @Name("next") String nextProtocol)
{ {
super("SSL"); super("SSL");
_sslContextFactory=factory==null?new SslContextFactory():factory; _sslContextFactory = factory == null ? new SslContextFactory.Server() : factory;
_nextProtocol=nextProtocol; _nextProtocol = nextProtocol;
addBean(_sslContextFactory); addBean(_sslContextFactory);
} }
public SslContextFactory getSslContextFactory() public SslContextFactory.Server getSslContextFactory()
{ {
return _sslContextFactory; return _sslContextFactory;
} }

View File

@ -1618,9 +1618,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (getServer() != null && (getServer().isStarting() || getServer().isStarted())) if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
{ {
Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class); Class<ContextHandlerCollection> handlerClass = ContextHandlerCollection.class;
for (int h = 0; contextCollections != null && h < contextCollections.length; h++) Handler[] contextCollections = getServer().getChildHandlersByClass(handlerClass);
((ContextHandlerCollection)contextCollections[h]).mapContexts(); if (contextCollections != null)
{
for (Handler contextCollection : contextCollections)
handlerClass.cast(contextCollection).mapContexts();
}
} }
} }

View File

@ -24,8 +24,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -36,15 +35,16 @@ import org.eclipse.jetty.server.HttpChannelState;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.ArrayTernaryTrie; import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.ArrayUtil; import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Trie; import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation; import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.SerializedExecutor;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** ContextHandlerCollection. /**
*
* This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a * This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a
* Map of contexts to it's contained handlers based * Map of contexts to it's contained handlers based
* on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s. * on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s.
@ -57,9 +57,9 @@ import org.eclipse.jetty.util.log.Logger;
public class ContextHandlerCollection extends HandlerCollection public class ContextHandlerCollection extends HandlerCollection
{ {
private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class); private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class);
private final SerializedExecutor _serializedExecutor = new SerializedExecutor();
private final ConcurrentMap<ContextHandler,Handler> _contextBranches = new ConcurrentHashMap<>(); @Deprecated
private volatile Trie<Map.Entry<String,Branch[]>> _pathBranches;
private Class<? extends ContextHandler> _contextClass = ContextHandler.class; private Class<? extends ContextHandler> _contextClass = ContextHandler.class;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -71,43 +71,57 @@ public class ContextHandlerCollection extends HandlerCollection
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public ContextHandlerCollection(ContextHandler... contexts) public ContextHandlerCollection(ContextHandler... contexts)
{ {
super(true,contexts); super(true);
setHandlers(contexts);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Remap the context paths. * Remap the contexts. Normally this is not required as context
* mapping is maintained as a side effect of {@link #setHandlers(Handler[])}
* However, if configuration changes in the deep handler structure (eg contextpath is changed), then
* this call will trigger a remapping.
* This method is mutually excluded from {@link #deployHandler(Handler, Callback)} and
* {@link #undeployHandler(Handler, Callback)}
*/ */
@ManagedOperation("update the mapping of context path to context") @ManagedOperation("Update the mapping of context path to context")
public void mapContexts() public void mapContexts()
{ {
_contextBranches.clear(); _serializedExecutor.execute(()->
Handler[] handlers = getHandlers();
if (handlers==null)
{ {
_pathBranches=new ArrayTernaryTrie<>(false,16); while(true)
return; {
} Handlers handlers = _handlers.get();
if (handlers==null)
break;
if (updateHandlers(handlers, newHandlers(handlers.getHandlers())))
break;
}
});
}
/* ------------------------------------------------------------ */
@Override
protected Handlers newHandlers(Handler[] handlers)
{
if (handlers==null || handlers.length==0)
return null;
// Create map of contextPath to handler Branch // Create map of contextPath to handler Branch
Map<String,Branch[]> map = new HashMap<>(); // A branch is a Handler that could contain 0 or more ContextHandlers
Map<String,Branch[]> path2Branches = new HashMap<>();
for (Handler handler:handlers) for (Handler handler:handlers)
{ {
Branch branch=new Branch(handler); Branch branch=new Branch(handler);
for (String contextPath : branch.getContextPaths()) for (String contextPath : branch.getContextPaths())
{ {
Branch[] branches=map.get(contextPath); Branch[] branches=path2Branches.get(contextPath);
map.put(contextPath, ArrayUtil.addToArray(branches, branch, Branch.class)); path2Branches.put(contextPath, ArrayUtil.addToArray(branches, branch, Branch.class));
} }
for (ContextHandler context : branch.getContextHandlers())
_contextBranches.putIfAbsent(context, branch.getHandler());
} }
// Sort the branches so those with virtual hosts are considered before those without // Sort the branches for each contextPath so those with virtual hosts are considered before those without
for (Map.Entry<String,Branch[]> entry: map.entrySet()) for (Map.Entry<String,Branch[]> entry: path2Branches.entrySet())
{ {
Branch[] branches=entry.getValue(); Branch[] branches=entry.getValue();
Branch[] sorted=new Branch[branches.length]; Branch[] sorted=new Branch[branches.length];
@ -123,69 +137,56 @@ public class ContextHandlerCollection extends HandlerCollection
// Loop until we have a big enough trie to hold all the context paths // Loop until we have a big enough trie to hold all the context paths
int capacity=512; int capacity=512;
Trie<Map.Entry<String,Branch[]>> trie; Mapping mapping;
loop: while(true) loop: while(true)
{ {
trie=new ArrayTernaryTrie<>(false,capacity); mapping = new Mapping(handlers, capacity);
for (Map.Entry<String,Branch[]> entry: map.entrySet()) for (Map.Entry<String,Branch[]> entry: path2Branches.entrySet())
{ {
if (!trie.put(entry.getKey().substring(1),entry)) if (!mapping._pathBranches.put(entry.getKey().substring(1),entry))
{ {
capacity+=512; capacity+=512;
continue loop; continue loop;
} }
} }
break loop; break;
} }
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
for (String ctx : trie.keySet()) for (String ctx : mapping._pathBranches.keySet())
LOG.debug("{}->{}",ctx,Arrays.asList(trie.get(ctx).getValue())); LOG.debug("{}->{}",ctx,Arrays.asList(mapping._pathBranches.get(ctx).getValue()));
} }
_pathBranches=trie;
// add new context branches to concurrent map
for (Branch[] branches: path2Branches.values())
{
for (Branch branch : branches)
{
for (ContextHandler context : branch.getContextHandlers())
mapping._contextBranches.put(context, branch.getHandler());
}
}
return mapping;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.handler.HandlerCollection#setHandlers(org.eclipse.jetty.server.server.Handler[])
*/
@Override
public void setHandlers(Handler[] handlers)
{
super.setHandlers(handlers);
if (isStarted())
mapContexts();
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
{
mapContexts();
super.doStart();
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.Handler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
*/
@Override @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, ServletException
{ {
Handler[] handlers = getHandlers(); Handlers handlers = _handlers.get();
if (handlers==null || handlers.length==0) if (handlers==null)
return; return;
Mapping mapping = (Mapping)handlers;
HttpChannelState async = baseRequest.getHttpChannelState(); HttpChannelState async = baseRequest.getHttpChannelState();
if (async.isAsync()) if (async.isAsync())
{ {
ContextHandler context=async.getContextHandler(); ContextHandler context=async.getContextHandler();
if (context!=null) if (context!=null)
{ {
Handler branch = _contextBranches.get(context); Handler branch = mapping._contextBranches.get(context);
if (branch==null) if (branch==null)
context.handle(target,baseRequest,request, response); context.handle(target,baseRequest,request, response);
@ -195,19 +196,19 @@ public class ContextHandlerCollection extends HandlerCollection
} }
} }
// data structure which maps a request to a context; first-best match wins
// { context path => [ context ] }
// }
if (target.startsWith("/")) if (target.startsWith("/"))
{ {
Trie<Map.Entry<String,Branch[]>> pathBranches = mapping._pathBranches;
if (pathBranches==null)
return;
int limit = target.length()-1; int limit = target.length()-1;
while (limit>=0) while (limit>=0)
{ {
// Get best match // Get best match
Map.Entry<String,Branch[]> branches = _pathBranches.getBest(target,1,limit); Map.Entry<String,Branch[]> branches = pathBranches.getBest(target,1,limit);
if (branches==null) if (branches==null)
break; break;
@ -227,10 +228,11 @@ public class ContextHandlerCollection extends HandlerCollection
} }
else else
{ {
// This may not work in all circumstances... but then I think it should never be called if (mapping.getHandlers()==null)
for (int i=0;i<handlers.length;i++) return;
for (int i=0;i<mapping.getHandlers().length;i++)
{ {
handlers[i].handle(target,baseRequest, request, response); mapping.getHandlers()[i].handle(target,baseRequest, request, response);
if ( baseRequest.isHandled()) if ( baseRequest.isHandled())
return; return;
} }
@ -238,11 +240,15 @@ public class ContextHandlerCollection extends HandlerCollection
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Add a context handler. /**
* Adds a context handler.
*
* @param contextPath The context path to add * @param contextPath The context path to add
* @param resourceBase the base (root) Resource * @param resourceBase the base (root) Resource
* @return the ContextHandler just added * @return the ContextHandler just added
* @deprecated Unused convenience method no longer supported.
*/ */
@Deprecated
public ContextHandler addContext(String contextPath,String resourceBase) public ContextHandler addContext(String contextPath,String resourceBase)
{ {
try try
@ -260,22 +266,90 @@ public class ContextHandlerCollection extends HandlerCollection
} }
} }
/* ------------------------------------------------------------ */
/**
* Thread safe deploy of a Handler.
* <p>
* This method is the equivalent of {@link #addHandler(Handler)},
* but its execution is non-block and mutually excluded from all
* other calls to {@link #deployHandler(Handler, Callback)} and
* {@link #undeployHandler(Handler, Callback)}.
* The handler may be added after this call returns.
* </p>
* @param handler the handler to deploy
* @param callback Called after handler has been added
*/
public void deployHandler(Handler handler, Callback callback)
{
if (handler.getServer()!=getServer())
handler.setServer(getServer());
_serializedExecutor.execute(new SerializedExecutor.ErrorHandlingTask()
{
@Override
public void run()
{
addHandler(handler);
callback.succeeded();
}
@Override
public void accept(Throwable throwable)
{
callback.failed(throwable);
}
});
}
/* ------------------------------------------------------------ */
/**
* Thread safe undeploy of a Handler.
* <p>
* This method is the equivalent of {@link #removeHandler(Handler)},
* but its execution is non-block and mutually excluded from all
* other calls to {@link #deployHandler(Handler,Callback)} and
* {@link #undeployHandler(Handler,Callback)}.
* The handler may be removed after this call returns.
* </p>
* @param handler The handler to undeploy
* @param callback Called after handler has been removed
*/
public void undeployHandler(Handler handler, Callback callback)
{
_serializedExecutor.execute(new SerializedExecutor.ErrorHandlingTask()
{
@Override
public void run()
{
removeHandler(handler);
callback.succeeded();
}
@Override
public void accept(Throwable throwable)
{
callback.failed(throwable);
}
});
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return The class to use to add new Contexts * @return The class to use to add new Contexts
* @deprecated Unused convenience mechanism not used.
*/ */
@Deprecated
public Class<?> getContextClass() public Class<?> getContextClass()
{ {
return _contextClass; return _contextClass;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param contextClass The class to use to add new Contexts * @param contextClass The class to use to add new Contexts
* @deprecated Unused convenience mechanism not used.
*/ */
@Deprecated
public void setContextClass(Class<? extends ContextHandler> contextClass) public void setContextClass(Class<? extends ContextHandler> contextClass)
{ {
if (contextClass ==null || !(ContextHandler.class.isAssignableFrom(contextClass))) if (contextClass ==null || !(ContextHandler.class.isAssignableFrom(contextClass)))
@ -342,5 +416,18 @@ public class ContextHandlerCollection extends HandlerCollection
} }
} }
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static class Mapping extends Handlers
{
private final Map<ContextHandler,Handler> _contextBranches = new HashMap<>();
private final Trie<Map.Entry<String,Branch[]>> _pathBranches;
private Mapping(Handler[] handlers, int capacity)
{
super(handlers);
_pathBranches = new ArrayTernaryTrie<>(false, capacity);
}
}
} }

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -47,7 +48,7 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
public class HandlerCollection extends AbstractHandlerContainer public class HandlerCollection extends AbstractHandlerContainer
{ {
private final boolean _mutableWhenRunning; private final boolean _mutableWhenRunning;
private volatile Handler[] _handlers; protected final AtomicReference<Handlers> _handlers = new AtomicReference<>();
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public HandlerCollection() public HandlerCollection()
@ -71,72 +72,93 @@ public class HandlerCollection extends AbstractHandlerContainer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return Returns the handlers. * @return the array of handlers.
*/ */
@Override @Override
@ManagedAttribute(value="Wrapped handlers", readonly=true) @ManagedAttribute(value="Wrapped handlers", readonly=true)
public Handler[] getHandlers() public Handler[] getHandlers()
{ {
return _handlers; Handlers handlers = _handlers.get();
return handlers==null ? null : handlers._handlers;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param handlers The handlers to set. * @param handlers the array of handlers to set.
*/ */
public void setHandlers(Handler[] handlers) public void setHandlers(Handler[] handlers)
{ {
if (!_mutableWhenRunning && isStarted()) if (!_mutableWhenRunning && isStarted())
throw new IllegalStateException(STARTED); throw new IllegalStateException(STARTED);
if (handlers!=null) while(true)
{ {
// check for loops if (updateHandlers(_handlers.get(), newHandlers(handlers)))
for (Handler handler:handlers) break;
if (handler == this || (handler instanceof HandlerContainer &&
Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this)))
throw new IllegalStateException("setHandler loop");
// Set server
for (Handler handler:handlers)
if (handler.getServer()!=getServer())
handler.setServer(getServer());
} }
Handler[] old=_handlers;;
_handlers = handlers;
updateBeans(old, handlers);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** protected Handlers newHandlers(Handler[] handlers)
* @see Handler#handle(String, Request, HttpServletRequest, HttpServletResponse) {
*/ if (handlers==null || handlers.length==0)
return null;
return new Handlers(handlers);
}
/* ------------------------------------------------------------ */
protected boolean updateHandlers(Handlers old, Handlers handlers)
{
if (handlers!=null)
{
// check for loops
for (Handler handler:handlers._handlers)
if (handler == this || (handler instanceof HandlerContainer &&
Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this)))
throw new IllegalStateException("setHandler loop");
// Set server
for (Handler handler:handlers._handlers)
if (handler.getServer()!=getServer())
handler.setServer(getServer());
}
if (_handlers.compareAndSet(old, handlers))
{
Handler[] oldBeans = old == null ? null : old._handlers;
Handler[] newBeans = handlers == null ? null : handlers._handlers;
updateBeans(oldBeans, newBeans);
return true;
}
return false;
}
/* ------------------------------------------------------------ */
@Override @Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException throws IOException, ServletException
{ {
if (_handlers!=null && isStarted()) if (isStarted())
{ {
MultiException mex=null; Handlers handlers = _handlers.get();
if (handlers==null)
return;
for (int i=0;i<_handlers.length;i++) MultiException mex=null;
for (Handler handler : handlers._handlers)
{ {
try try
{ {
_handlers[i].handle(target,baseRequest, request, response); handler.handle(target, baseRequest, request, response);
} }
catch(IOException e) catch (IOException | RuntimeException e)
{ {
throw e; throw e;
} }
catch(RuntimeException e) catch (Exception e)
{ {
throw e; if (mex == null)
} mex = new MultiException();
catch(Exception e)
{
if (mex==null)
mex=new MultiException();
mex.add(e); mex.add(e);
} }
} }
@ -147,37 +169,54 @@ public class HandlerCollection extends AbstractHandlerContainer
else else
throw new ServletException(mex); throw new ServletException(mex);
} }
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* Add a handler. /**
* Adds a handler.
* This implementation adds the passed handler to the end of the existing collection of handlers. * This implementation adds the passed handler to the end of the existing collection of handlers.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler) * If the handler is already added, it is removed and readded
*/ */
public void addHandler(Handler handler) public void addHandler(Handler handler)
{ {
setHandlers(ArrayUtil.addToArray(getHandlers(), handler, Handler.class)); while(true)
{
Handlers old = _handlers.get();
Handlers handlers = newHandlers(ArrayUtil.addToArray(old==null?null:ArrayUtil.removeFromArray(old._handlers, handler), handler, Handler.class));
if (updateHandlers(old,handlers))
break;
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* Prepend a handler. /**
* Prepends a handler.
* This implementation adds the passed handler to the start of the existing collection of handlers. * This implementation adds the passed handler to the start of the existing collection of handlers.
* @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
*/ */
public void prependHandler(Handler handler) public void prependHandler(Handler handler)
{ {
setHandlers(ArrayUtil.prependToArray(handler, getHandlers(), Handler.class)); while(true)
{
Handlers old = _handlers.get();
Handlers handlers = newHandlers(ArrayUtil.prependToArray(handler, old==null?null:old._handlers, Handler.class));
if (updateHandlers(old,handlers))
break;
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void removeHandler(Handler handler) public void removeHandler(Handler handler)
{ {
Handler[] handlers = getHandlers(); while(true)
{
if (handlers!=null && handlers.length>0 ) Handlers old = _handlers.get();
setHandlers(ArrayUtil.removeFromArray(handlers, handler)); if (old==null || old._handlers.length==0)
break;
Handlers handlers = newHandlers(ArrayUtil.removeFromArray(old._handlers, handler));
if (updateHandlers(old,handlers))
break;
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -196,10 +235,28 @@ public class HandlerCollection extends AbstractHandlerContainer
{ {
if (!isStopped()) if (!isStopped())
throw new IllegalStateException("!STOPPED"); throw new IllegalStateException("!STOPPED");
Handler[] children=getChildHandlers(); Handler[] children = getChildHandlers();
setHandlers(null); setHandlers(null);
for (Handler child: children) for (Handler child: children)
child.destroy(); child.destroy();
super.destroy(); super.destroy();
} }
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
protected static class Handlers
{
private final Handler[] _handlers;
protected Handlers(Handler[] handlers)
{
this._handlers = handlers;
}
public Handler[] getHandlers()
{
return _handlers;
}
}
} }

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;

View File

@ -170,7 +170,7 @@ public class ConnectionOpenCloseTest extends AbstractHttpTest
@DisabledIfSystemProperty(named = "env", matches = "ci") // TODO: SLOW, needs review @DisabledIfSystemProperty(named = "env", matches = "ci") // TODO: SLOW, needs review
public void testSSLOpenRequestClose() throws Exception public void testSSLOpenRequestClose() throws Exception
{ {
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
sslContextFactory.setKeyStoreResource(Resource.newResource(keystore)); sslContextFactory.setKeyStoreResource(Resource.newResource(keystore));
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");

View File

@ -52,7 +52,7 @@ public class OptionalSslConnectionTest
server = new Server(serverThreads); server = new Server(serverThreads);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystore); sslContextFactory.setKeyStorePath(keystore);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");
@ -113,7 +113,7 @@ public class OptionalSslConnectionTest
} }
// Then try a SSL connection. // Then try a SSL connection.
SslContextFactory sslContextFactory = new SslContextFactory(true); SslContextFactory sslContextFactory = new SslContextFactory.Client(true);
sslContextFactory.start(); sslContextFactory.start();
try (Socket ssl = sslContextFactory.newSslSocket()) try (Socket ssl = sslContextFactory.newSslSocket())
{ {

View File

@ -18,17 +18,17 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertNull;
/** /**
* *
*/ */
@ -82,6 +82,7 @@ public class ProxyConnectionTest
} }
@Test @Test
@Tag("ipv6")
public void testIPv6() throws Exception public void testIPv6() throws Exception
{ {
String response=_connector.getResponse("PROXY UNKNOWN eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n"+ String response=_connector.getResponse("PROXY UNKNOWN eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n"+

View File

@ -18,11 +18,6 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -33,7 +28,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -56,12 +50,16 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.Scheduler;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ThreadStarvationTest public class ThreadStarvationTest
{ {
final static int BUFFER_SIZE=1024*1024; final static int BUFFER_SIZE=1024*1024;
@ -82,14 +80,14 @@ public class ThreadStarvationTest
List<Scenario> params = new ArrayList<>(); List<Scenario> params = new ArrayList<>();
// HTTP // HTTP
ConnectorProvider http = (server, acceptors, selectors) -> new ServerConnector(server, acceptors, selectors); ConnectorProvider http = ServerConnector::new;
ClientSocketProvider httpClient = (host, port) -> new Socket(host, port); ClientSocketProvider httpClient = Socket::new;
params.add(new Scenario("http", http, httpClient)); params.add(new Scenario("http", http, httpClient));
// HTTPS/SSL/TLS // HTTPS/SSL/TLS
ConnectorProvider https = (server, acceptors, selectors) -> { ConnectorProvider https = (server, acceptors, selectors) -> {
Path keystorePath = MavenTestingUtils.getTestResourcePath("keystore"); Path keystorePath = MavenTestingUtils.getTestResourcePath("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystorePath.toString()); sslContextFactory.setKeyStorePath(keystorePath.toString());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");
@ -98,8 +96,7 @@ public class ThreadStarvationTest
ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(); HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory();
ServerConnector connector = new ServerConnector(server,(Executor)null,(Scheduler)null, ServerConnector connector = new ServerConnector(server, null, null, pool, acceptors, selectors,
pool, acceptors, selectors,
AbstractConnectionFactory.getFactories(sslContextFactory,httpConnectionFactory)); AbstractConnectionFactory.getFactories(sslContextFactory,httpConnectionFactory));
SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer(); SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer();
secureRequestCustomer.setSslSessionAttribute("SSL_SESSION"); secureRequestCustomer.setSslSessionAttribute("SSL_SESSION");
@ -312,8 +309,8 @@ public class ThreadStarvationTest
// Read Response // Read Response
long bodyCount = 0; long bodyCount = 0;
long len; long len;
byte buf[] = new byte[1024]; byte[] buf = new byte[1024];
try try
{ {
@ -343,7 +340,7 @@ public class ThreadStarvationTest
for (Future<Long> responseFut : responses) for (Future<Long> responseFut : responses)
{ {
Long bodyCount = responseFut.get(); Long bodyCount = responseFut.get();
assertThat(bodyCount.longValue(), is(expected)); assertThat(bodyCount, is(expected));
} }
} }
finally finally

View File

@ -18,16 +18,6 @@
package org.eclipse.jetty.server.handler; package org.eclipse.jetty.server.handler;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException; import java.io.IOException;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
@ -41,9 +31,18 @@ import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class ContextHandlerCollectionTest public class ContextHandlerCollectionTest
{ {
@Test @Test
@ -214,7 +213,7 @@ public class ContextHandlerCollectionTest
IsHandledHandler handler = (IsHandledHandler)context.getHandler(); IsHandledHandler handler = (IsHandledHandler)context.getHandler();
context.setVirtualHosts(contextHosts); context.setVirtualHosts(contextHosts);
// trigger this manually; it's supposed to be called when adding the handler // trigger this manually
handlerCollection.mapContexts(); handlerCollection.mapContexts();
for(String host : requestHosts) for(String host : requestHosts)

View File

@ -18,11 +18,6 @@
package org.eclipse.jetty.server.handler; package org.eclipse.jetty.server.handler;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -31,14 +26,11 @@ import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.KeyStore; import java.security.KeyStore;
import java.util.concurrent.Executor;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -53,21 +45,18 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Scheduler;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
public class DebugHandlerTest public class DebugHandlerTest
{ {
public final static HostnameVerifier __hostnameverifier = new HostnameVerifier() public final static HostnameVerifier __hostnameverifier = (hostname, session) -> true;
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
}
};
private SSLContext sslContext; private SSLContext sslContext;
private Server server; private Server server;
@ -77,7 +66,6 @@ public class DebugHandlerTest
private DebugHandler debugHandler; private DebugHandler debugHandler;
private ByteArrayOutputStream capturedLog; private ByteArrayOutputStream capturedLog;
@SuppressWarnings("deprecation")
@BeforeEach @BeforeEach
public void startServer() throws Exception public void startServer() throws Exception
{ {
@ -88,16 +76,14 @@ public class DebugHandlerTest
server.addConnector(httpConnector); server.addConnector(httpConnector);
File keystorePath = MavenTestingUtils.getTestResourceFile("keystore"); File keystorePath = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystorePath.getAbsolutePath()); sslContextFactory.setKeyStorePath(keystorePath.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setTrustStorePath(keystorePath.getAbsolutePath()); sslContextFactory.setTrustStorePath(keystorePath.getAbsolutePath());
sslContextFactory.setTrustStorePassword("storepwd"); sslContextFactory.setTrustStorePassword("storepwd");
ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
ServerConnector sslConnector = new ServerConnector(server, ServerConnector sslConnector = new ServerConnector(server, null, null, pool, 1, 1,
(Executor)null,
(Scheduler)null, pool, 1, 1,
AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory())); AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
server.addConnector(sslConnector); server.addConnector(sslConnector);
@ -108,7 +94,7 @@ public class DebugHandlerTest
debugHandler.setHandler(new AbstractHandler() debugHandler.setHandler(new AbstractHandler()
{ {
@Override @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); baseRequest.setHandled(true);
response.setStatus(HttpStatus.OK_200); response.setStatus(HttpStatus.OK_200);

View File

@ -167,7 +167,7 @@ public class ResourceHandlerTest
_local.getResponse("GET /resource/ HTTP/1.0\r\n\r\n")); _local.getResponse("GET /resource/ HTTP/1.0\r\n\r\n"));
assertThat(response.getStatus(),equalTo(200)); assertThat(response.getStatus(),equalTo(200));
assertThat(response.getContent(),containsString("jetty-dir.css")); assertThat(response.getContent(),containsString("jetty-dir.css"));
assertThat(response.getContent(),containsString("<H1>Directory: /resource/")); assertThat(response.getContent(),containsString("Directory: /resource/"));
assertThat(response.getContent(),containsString("big.txt")); assertThat(response.getContent(),containsString("big.txt"));
assertThat(response.getContent(),containsString("bigger.txt")); assertThat(response.getContent(),containsString("bigger.txt"));
assertThat(response.getContent(),containsString("directory")); assertThat(response.getContent(),containsString("directory"));

View File

@ -18,10 +18,6 @@
package org.eclipse.jetty.server.handler; package org.eclipse.jetty.server.handler;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -55,6 +51,10 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
public class SecuredRedirectHandlerTest public class SecuredRedirectHandlerTest
{ {
private static Server server; private static Server server;
@ -68,7 +68,7 @@ public class SecuredRedirectHandlerTest
{ {
// Setup SSL // Setup SSL
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystore.getAbsolutePath()); sslContextFactory.setKeyStorePath(keystore.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

View File

@ -27,7 +27,6 @@ import java.net.Socket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -37,7 +36,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -48,7 +46,7 @@ public class SSLCloseTest
public void testClose() throws Exception public void testClose() throws Exception
{ {
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(Resource.newResource(keystore)); sslContextFactory.setKeyStoreResource(Resource.newResource(keystore));
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

View File

@ -23,12 +23,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -63,6 +57,12 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* *
*/ */
@ -109,7 +109,7 @@ public class SSLEngineTest
public void startServer() throws Exception public void startServer() throws Exception
{ {
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath(); String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystore); sslContextFactory.setKeyStorePath(keystore);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

View File

@ -18,9 +18,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -30,7 +27,6 @@ import java.net.Socket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -46,6 +42,9 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnJre; import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.condition.JRE;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
// Only in JDK 11 is possible to use SSLSocket.shutdownOutput(). // Only in JDK 11 is possible to use SSLSocket.shutdownOutput().
@DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_10}) @DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9, JRE.JAVA_10})
public class SSLReadEOFAfterResponseTest public class SSLReadEOFAfterResponseTest
@ -54,7 +53,7 @@ public class SSLReadEOFAfterResponseTest
public void testReadEOFAfterResponse() throws Exception public void testReadEOFAfterResponse() throws Exception
{ {
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(Resource.newResource(keystore)); sslContextFactory.setKeyStoreResource(Resource.newResource(keystore));
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");
@ -70,7 +69,7 @@ public class SSLReadEOFAfterResponseTest
server.setHandler(new AbstractHandler.ErrorDispatchHandler() server.setHandler(new AbstractHandler.ErrorDispatchHandler()
{ {
@Override @Override
protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
{ {
// First: read the whole content. // First: read the whole content.
InputStream input = request.getInputStream(); InputStream input = request.getInputStream();

View File

@ -18,9 +18,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@ -53,6 +50,9 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class SSLSelectChannelConnectorLoadTest public class SSLSelectChannelConnectorLoadTest
{ {
private static Server server; private static Server server;
@ -63,7 +63,7 @@ public class SSLSelectChannelConnectorLoadTest
public static void startServer() throws Exception public static void startServer() throws Exception
{ {
String keystorePath = System.getProperty("basedir", ".") + "/src/test/resources/keystore"; String keystorePath = System.getProperty("basedir", ".") + "/src/test/resources/keystore";
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystorePath); sslContextFactory.setKeyStorePath(keystorePath);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

View File

@ -18,14 +18,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.condition.OS.WINDOWS;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -62,11 +54,19 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.DisabledOnOs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.condition.OS.WINDOWS;
/** /**
* HttpServer Tester. * HttpServer Tester.
*/ */
@ -83,7 +83,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
public void init() throws Exception public void init() throws Exception
{ {
String keystorePath = MavenTestingUtils.getTestResourcePath("keystore").toString(); String keystorePath = MavenTestingUtils.getTestResourcePath("keystore").toString();
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystorePath); sslContextFactory.setKeyStorePath(keystorePath);
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.server.ssl; package org.eclipse.jetty.server.ssl;
import static java.time.Duration.ofSeconds;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -51,6 +49,8 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static java.time.Duration.ofSeconds;
@Tag("Unstable") @Tag("Unstable")
@Disabled @Disabled
public class SlowClientsTest public class SlowClientsTest
@ -61,7 +61,7 @@ public class SlowClientsTest
public void testSlowClientsWithSmallThreadPool() throws Exception public void testSlowClientsWithSmallThreadPool() throws Exception
{ {
File keystore = MavenTestingUtils.getTestResourceFile("keystore"); File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory sslContextFactory = new SslContextFactory(); SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath(keystore.getAbsolutePath()); sslContextFactory.setKeyStorePath(keystore.getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd"); sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd"); sslContextFactory.setKeyManagerPassword("keypwd");

Some files were not shown because too many files have changed in this diff Show More