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:
commit
002ecf526d
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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].
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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"+
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue