summaryrefslogtreecommitdiffstats
path: root/container-core/src/test/java/com/yahoo/jdisc/http/server
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2021-04-12 12:21:45 +0200
committerGitHub <noreply@github.com>2021-04-12 12:21:45 +0200
commitd63e3d7e5b5d31fd485fc710c97d674904f13754 (patch)
treec019d2ece68973a01407121d3726c6ec2fe74aef /container-core/src/test/java/com/yahoo/jdisc/http/server
parentf7dc9f789dcec46b0c3365878b1100ef2e9a37d4 (diff)
Revert "Revert "Revert "Bjorncs/jdisc http2 preps [run-systemtest]"""
Diffstat (limited to 'container-core/src/test/java/com/yahoo/jdisc/http/server')
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLogTest.java89
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/FilterTestCase.java2
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactoryTest.java30
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java108
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServletTest.java23
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockRequestBuilder.java176
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockResponseBuilder.java29
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java83
-rw-r--r--container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/TestDrivers.java5
9 files changed, 162 insertions, 383 deletions
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLogTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLogTest.java
index c45d17a4ff8..e472f954afc 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLogTest.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/AccessLogRequestLogTest.java
@@ -4,7 +4,12 @@ package com.yahoo.jdisc.http.server.jetty;
import com.yahoo.container.logging.AccessLogEntry;
import com.yahoo.container.logging.RequestLog;
import com.yahoo.container.logging.RequestLogEntry;
+import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.ServerConfig;
+import org.eclipse.jetty.http.MetaData;
+import org.eclipse.jetty.server.HttpChannel;
+import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.HttpInput;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.junit.Test;
@@ -18,6 +23,8 @@ import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* @author Oyvind Bakksjo
@@ -26,9 +33,9 @@ import static org.junit.Assert.assertTrue;
public class AccessLogRequestLogTest {
@Test
public void requireThatQueryWithUnquotedSpecialCharactersIsHandled() {
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, "/search/", "query=year:>2010")
- .build();
+ final Request jettyRequest = createRequestMock();
+ when(jettyRequest.getRequestURI()).thenReturn("/search/");
+ when(jettyRequest.getQueryString()).thenReturn("query=year:>2010");
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -40,11 +47,11 @@ public class AccessLogRequestLogTest {
@Test
public void requireThatDoubleQuotingIsNotPerformed() {
- String path = "/search/";
- String query = "query=year%252010+%3B&customParameter=something";
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, path, query)
- .build();
+ final Request jettyRequest = createRequestMock();
+ final String path = "/search/";
+ when(jettyRequest.getRequestURI()).thenReturn(path);
+ final String query = "query=year%252010+%3B&customParameter=something";
+ when(jettyRequest.getQueryString()).thenReturn(query);
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -57,11 +64,11 @@ public class AccessLogRequestLogTest {
@Test
public void raw_path_and_query_are_set_from_request() {
+ Request jettyRequest = createRequestMock();
String rawPath = "//search/";
+ when(jettyRequest.getRequestURI()).thenReturn(rawPath);
String rawQuery = "q=%%2";
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, rawPath, rawQuery)
- .build();
+ when(jettyRequest.getQueryString()).thenReturn(rawQuery);
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -74,11 +81,11 @@ public class AccessLogRequestLogTest {
@Test
public void verify_x_forwarded_for_precedence () {
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, "//search/", "q=%%2")
- .header("x-forwarded-for", List.of("1.2.3.4"))
- .header("y-ra", List.of("2.3.4.5"))
- .build();
+ Request jettyRequest = createRequestMock();
+ when(jettyRequest.getRequestURI()).thenReturn("//search/");
+ when(jettyRequest.getQueryString()).thenReturn("q=%%2");
+ when(jettyRequest.getHeader("x-forwarded-for")).thenReturn("1.2.3.4");
+ when(jettyRequest.getHeader("y-ra")).thenReturn("2.3.4.5");
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -88,11 +95,11 @@ public class AccessLogRequestLogTest {
@Test
public void verify_x_forwarded_port_precedence () {
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, "//search/", "q=%%2")
- .header("X-Forwarded-Port", List.of("80"))
- .header("y-rp", List.of("8080"))
- .build();
+ Request jettyRequest = createRequestMock();
+ when(jettyRequest.getRequestURI()).thenReturn("//search/");
+ when(jettyRequest.getQueryString()).thenReturn("q=%%2");
+ when(jettyRequest.getHeader("X-Forwarded-Port")).thenReturn("80");
+ when(jettyRequest.getHeader("y-rp")).thenReturn("8080");
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -102,12 +109,10 @@ public class AccessLogRequestLogTest {
@Test
public void defaults_to_peer_port_if_remote_port_header_is_invalid() {
- Request jettyRequest = createRequestBuilder()
- .uri("http", "localhost", 12345, "/search/", null)
- .header("X-Forwarded-Port", List.of("8o8o"))
- .header("y-rp", List.of("8o8o"))
- .remote("2.3.4.5", "localhost", 80)
- .build();
+ final Request jettyRequest = createRequestMock();
+ when(jettyRequest.getRequestURI()).thenReturn("/search/");
+ when(jettyRequest.getHeader("X-Forwarded-Port")).thenReturn("8o8o");
+ when(jettyRequest.getRemotePort()).thenReturn(80);
InMemoryRequestLog requestLog = new InMemoryRequestLog();
doAccessLoggingOfRequest(requestLog, jettyRequest);
@@ -124,14 +129,32 @@ public class AccessLogRequestLogTest {
new AccessLogRequestLog(requestLog, config).log(jettyRequest, createResponseMock());
}
- private static JettyMockRequestBuilder createRequestBuilder() {
- return JettyMockRequestBuilder.newBuilder()
- .attribute(JDiscHttpServlet.ATTRIBUTE_NAME_ACCESS_LOG_ENTRY, new AccessLogEntry())
- .remote("2.3.4.5", "localhost", 12345)
- .localPort(1234);
+ private static Request createRequestMock() {
+ JDiscServerConnector serverConnector = mock(JDiscServerConnector.class);
+ int localPort = 1234;
+ when(serverConnector.connectorConfig()).thenReturn(new ConnectorConfig(new ConnectorConfig.Builder().listenPort(localPort)));
+ when(serverConnector.getLocalPort()).thenReturn(localPort);
+ HttpConnection httpConnection = mock(HttpConnection.class);
+ when(httpConnection.getConnector()).thenReturn(serverConnector);
+ Request request = mock(Request.class);
+ when(request.getMethod()).thenReturn("GET");
+ when(request.getRemoteAddr()).thenReturn("localhost");
+ when(request.getRemotePort()).thenReturn(12345);
+ when(request.getProtocol()).thenReturn("HTTP/1.1");
+ when(request.getScheme()).thenReturn("http");
+ when(request.getTimeStamp()).thenReturn(0L);
+ when(request.getAttribute(JDiscHttpServlet.ATTRIBUTE_NAME_ACCESS_LOG_ENTRY)).thenReturn(new AccessLogEntry());
+ when(request.getAttribute("org.eclipse.jetty.server.HttpConnection")).thenReturn(httpConnection);
+ HttpInput httpInput = mock(HttpInput.class);
+ when(httpInput.getContentReceived()).thenReturn(2345L);
+ when(request.getHttpInput()).thenReturn(httpInput);
+ return request;
}
private Response createResponseMock() {
- return JettyMockResponseBuilder.newBuilder().build();
+ Response response = mock(Response.class);
+ when(response.getHttpChannel()).thenReturn(mock(HttpChannel.class));
+ when(response.getCommittedMetaData()).thenReturn(mock(MetaData.Response.class));
+ return response;
}
}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/FilterTestCase.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/FilterTestCase.java
index e117ef7f723..a67656dd5ca 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/FilterTestCase.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/FilterTestCase.java
@@ -99,7 +99,7 @@ public class FilterTestCase {
final MyRequestHandler requestHandler = new MyRequestHandler();
final TestDriver testDriver = newDriver(requestHandler, filterBindings);
- testDriver.client().get("/status.html");
+ testDriver.client().get("status.html");
assertThat(requestHandler.awaitInvocation(), is(true));
assertThat(requestHandler.getHeaderMap().get("foo").get(0), is("bar"));
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactoryTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactoryTest.java
index fbbf3074839..9c1348004ee 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactoryTest.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpRequestFactoryTest.java
@@ -7,8 +7,10 @@ import com.yahoo.jdisc.References;
import com.yahoo.jdisc.ResourceReference;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.handler.RequestHandler;
+import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.HttpRequest;
import com.yahoo.jdisc.service.CurrentContainer;
+import org.eclipse.jetty.server.HttpConnection;
import org.junit.Test;
import javax.servlet.http.HttpServletRequest;
@@ -20,6 +22,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* @author Steinar Knutsen
@@ -137,15 +141,27 @@ public class HttpRequestFactoryTest {
assertEquals(LOCAL_PORT, request.getUri().getPort());
}
- private HttpServletRequest createMockRequest(String scheme, String host, String path, String query) {
- return JettyMockRequestBuilder.newBuilder()
- .uri(scheme, host, LOCAL_PORT, path, query)
- .remote("127.0.0.1", "localhost", 1234)
- .localPort(LOCAL_PORT)
- .build();
+ private static HttpServletRequest createMockRequest(String scheme, String serverName, String path, String queryString) {
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ HttpConnection connection = mock(HttpConnection.class);
+ JDiscServerConnector connector = mock(JDiscServerConnector.class);
+ when(connector.connectorConfig()).thenReturn(new ConnectorConfig(new ConnectorConfig.Builder().listenPort(LOCAL_PORT)));
+ when(connector.getLocalPort()).thenReturn(LOCAL_PORT);
+ when(connection.getCreatedTimeStamp()).thenReturn(System.currentTimeMillis());
+ when(connection.getConnector()).thenReturn(connector);
+ when(request.getAttribute("org.eclipse.jetty.server.HttpConnection")).thenReturn(connection);
+ when(request.getProtocol()).thenReturn("HTTP/1.1");
+ when(request.getScheme()).thenReturn(scheme);
+ when(request.getServerName()).thenReturn(serverName);
+ when(request.getRemoteAddr()).thenReturn("127.0.0.1");
+ when(request.getRemotePort()).thenReturn(1234);
+ when(request.getLocalPort()).thenReturn(LOCAL_PORT);
+ when(request.getMethod()).thenReturn("GET");
+ when(request.getQueryString()).thenReturn(queryString);
+ when(request.getRequestURI()).thenReturn(path);
+ return request;
}
-
private static final class MockContainer implements CurrentContainer {
@Override
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
index f5d77b53f12..d8e94d13813 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/HttpServerTest.java
@@ -35,19 +35,10 @@ import com.yahoo.security.SslContextBuilder;
import com.yahoo.security.X509CertificateBuilder;
import com.yahoo.security.X509CertificateUtils;
import com.yahoo.security.tls.TlsContext;
-import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
-import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
-import org.apache.hc.client5.http.entity.mime.FormBodyPart;
-import org.apache.hc.client5.http.entity.mime.FormBodyPartBuilder;
-import org.apache.hc.client5.http.entity.mime.StringBody;
-import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
-import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
-import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
-import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
-import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
-import org.apache.hc.core5.http.ContentType;
-import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.FormBodyPart;
+import org.apache.http.entity.mime.content.StringBody;
import org.assertj.core.api.Assertions;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.ProxyProtocolClientConnectionFactory.V1;
@@ -116,7 +107,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@@ -410,8 +400,8 @@ public class HttpServerTest {
final ResponseValidator response =
driver.client().newPost("/status.html")
.setMultipartContent(
- newFileBody("start.txt", startTxtContent),
- newFileBody("updater.conf", updaterConfContent))
+ newFileBody("", "start.txt", startTxtContent),
+ newFileBody("", "updater.conf", updaterConfContent))
.execute();
response.expectStatusCode(is(OK))
.expectContent(containsString(startTxtContent))
@@ -515,27 +505,11 @@ public class HttpServerTest {
}
@Test
- public void requireThatServerCanRespondToHttp2Request() throws Exception {
- Path privateKeyFile = tmpFolder.newFile().toPath();
- Path certificateFile = tmpFolder.newFile().toPath();
- generatePrivateKeyAndCertificate(privateKeyFile, certificateFile);
-
- TestDriver driver = TestDrivers.newInstanceWithSsl(new EchoRequestHandler(), certificateFile, privateKeyFile, TlsClientAuth.WANT);
- try (CloseableHttpAsyncClient client = createHttp2Client(certificateFile, privateKeyFile)) {
- String uri = "https://localhost:" + driver.server().getListenPort() + "/status.html";
- SimpleHttpResponse response = client.execute(SimpleHttpRequests.get(uri), null).get();
- assertNull(response.getBodyText());
- assertEquals(OK, response.getCode());
- }
- assertTrue(driver.close());
- }
-
- @Test
public void requireThatTlsClientAuthenticationEnforcerRejectsRequestsForNonWhitelistedPaths() throws IOException {
Path privateKeyFile = tmpFolder.newFile().toPath();
Path certificateFile = tmpFolder.newFile().toPath();
generatePrivateKeyAndCertificate(privateKeyFile, certificateFile);
- TestDriver driver = createSslWithTlsClientAuthenticationEnforcer(certificateFile, privateKeyFile);
+ TestDriver driver = TestDrivers.newInstanceWithSsl(new EchoRequestHandler(), certificateFile, privateKeyFile, TlsClientAuth.WANT);
SSLContext trustStoreOnlyCtx = new SslContextBuilder()
.withTrustStore(certificateFile)
@@ -944,21 +918,6 @@ public class HttpServerTest {
return client;
}
- private static CloseableHttpAsyncClient createHttp2Client(Path certificateFile, Path privateKeyFile) {
- TestDriver driver = TestDrivers.newInstanceWithSsl(new EchoRequestHandler(), certificateFile, privateKeyFile, TlsClientAuth.WANT);
- TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
- .setSslContext(driver.newSslContext())
- .build();
- var client = HttpAsyncClientBuilder.create()
- .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
- .disableConnectionState()
- .disableAutomaticRetries()
- .setConnectionManager(PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(tlsStrategy).build())
- .build();
- client.start();
- return client;
- }
-
private static void assertLogEntryHasRemote(RequestLogEntry entry, String expectedAddress, int expectedPort) {
assertEquals(expectedAddress, entry.peerAddress().get());
if (expectedPort > 0) {
@@ -1010,25 +969,6 @@ public class HttpServerTest {
});
}
- private static TestDriver createSslWithTlsClientAuthenticationEnforcer(Path certificateFile, Path privateKeyFile) {
- ConnectorConfig.Builder connectorConfig = new ConnectorConfig.Builder()
- .tlsClientAuthEnforcer(
- new ConnectorConfig.TlsClientAuthEnforcer.Builder()
- .enable(true)
- .pathWhitelist("/status.html"))
- .ssl(new ConnectorConfig.Ssl.Builder()
- .enabled(true)
- .clientAuth(ConnectorConfig.Ssl.ClientAuth.Enum.WANT_AUTH)
- .privateKeyFile(privateKeyFile.toString())
- .certificateFile(certificateFile.toString())
- .caCertificateFile(certificateFile.toString()));
- return TestDrivers.newConfiguredInstance(
- new EchoRequestHandler(),
- new ServerConfig.Builder().connectionLog(new ServerConfig.ConnectionLog.Builder().enabled(true)),
- connectorConfig,
- binder -> {});
- }
-
private static TestDriver createSslTestDriver(
Path serverCertificateFile, Path serverPrivateKeyFile, MetricConsumerMock metricConsumer, InMemoryConnectionLog connectionLog) throws IOException {
Module extraModule = binder -> {
@@ -1109,16 +1049,30 @@ public class HttpServerTest {
new ConnectorConfig.Builder());
}
- private static FormBodyPart newFileBody(final String fileName, final String fileContent) {
- return FormBodyPartBuilder.create()
- .setBody(
- new StringBody(fileContent, ContentType.TEXT_PLAIN) {
- @Override public String getFilename() { return fileName; }
- @Override public String getMimeType() { return ""; }
- @Override public String getCharset() { return null; }
- })
- .setName(fileName)
- .build();
+ private static FormBodyPart newFileBody(final String parameterName, final String fileName, final String fileContent) {
+ return new FormBodyPart(
+ parameterName,
+ new StringBody(fileContent, ContentType.TEXT_PLAIN) {
+ @Override
+ public String getFilename() {
+ return fileName;
+ }
+
+ @Override
+ public String getTransferEncoding() {
+ return "binary";
+ }
+
+ @Override
+ public String getMimeType() {
+ return "";
+ }
+
+ @Override
+ public String getCharset() {
+ return null;
+ }
+ });
}
private static class ConnectedAtRequestHandler extends AbstractRequestHandler {
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServletTest.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServletTest.java
index 23c229e2ec5..230f59cbb34 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServletTest.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JDiscHttpServletTest.java
@@ -7,15 +7,15 @@ import com.yahoo.jdisc.handler.AbstractRequestHandler;
import com.yahoo.jdisc.handler.ContentChannel;
import com.yahoo.jdisc.handler.RequestHandler;
import com.yahoo.jdisc.handler.ResponseHandler;
-import org.apache.hc.client5.http.classic.methods.HttpDelete;
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.classic.methods.HttpHead;
-import org.apache.hc.client5.http.classic.methods.HttpOptions;
-import org.apache.hc.client5.http.classic.methods.HttpPatch;
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.classic.methods.HttpPut;
-import org.apache.hc.client5.http.classic.methods.HttpTrace;
-import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpOptions;
+import org.apache.http.client.methods.HttpPatch;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.HttpTrace;
import org.junit.Test;
import java.io.IOException;
@@ -73,7 +73,8 @@ public class JDiscHttpServletTest {
};
}
- private static class UnknownMethodHttpRequest extends HttpUriRequestBase {
- UnknownMethodHttpRequest(URI uri) { super("UNKNOWN_METHOD", uri); }
+ private static class UnknownMethodHttpRequest extends HttpRequestBase {
+ UnknownMethodHttpRequest(URI uri) { setURI(uri); }
+ @Override public String getMethod() { return "UNKNOWN_METHOD"; }
}
}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockRequestBuilder.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockRequestBuilder.java
deleted file mode 100644
index 4bf6afeb3f1..00000000000
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockRequestBuilder.java
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import com.yahoo.jdisc.http.ConnectorConfig;
-import org.eclipse.jetty.server.HttpChannel;
-import org.eclipse.jetty.server.HttpConnection;
-import org.eclipse.jetty.server.HttpInput;
-import org.eclipse.jetty.server.Request;
-import org.mockito.stubbing.Answer;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * Builder for creating a mock instance of Jetty's {@link Request} type.
- *
- * @author bjorncs
- */
-public class JettyMockRequestBuilder {
-
- private final Map<String, List<String>> parameters = new HashMap<>();
- private final Map<String, List<String>> headers = new HashMap<>();
- private final Map<String, Object> attributes = new HashMap<>();
- private Integer localPort;
- private String uriScheme;
- private String uriServerName;
- private Integer uriPort;
- private String uriPath;
- private String uriQuery;
- private String remoteAddress;
- private String remoteHost;
- private Integer remotePort;
-
- private JettyMockRequestBuilder() {}
-
- public static JettyMockRequestBuilder newBuilder() { return new JettyMockRequestBuilder(); }
-
- public JettyMockRequestBuilder localPort(int localPort) { this.localPort = localPort; return this; }
-
- public JettyMockRequestBuilder remote(String address, String host, int port) {
- this.remoteAddress = address;
- this.remoteHost = host;
- this.remotePort = port;
- return this;
- }
-
- public JettyMockRequestBuilder uri(String scheme, String serverName, int port, String path, String query) {
- this.uriScheme = scheme;
- this.uriServerName = serverName;
- this.uriPort = port;
- this.uriPath = path;
- this.uriQuery = query;
- return this;
- }
-
- public JettyMockRequestBuilder parameter(String name, List<String> values) { this.parameters.put(name, List.copyOf(values)); return this; }
-
- public JettyMockRequestBuilder header(String name, List<String> values) { this.headers.put(name, List.copyOf(values)); return this; }
-
- public JettyMockRequestBuilder attribute(String name, Object value) { this.attributes.put(name, value); return this; }
-
- public Request build() {
- int localPort = this.localPort != null ? this.localPort : 8080;
- String scheme = this.uriScheme != null ? this.uriScheme : "http";
- String serverName = this.uriServerName != null ? this.uriServerName : "localhost";
- int uriPort = this.uriPort != null ? this.uriPort : 8080;
- String path = this.uriPath;
- String query = this.uriQuery;
- String remoteAddress = this.remoteAddress != null ? this.remoteAddress : "1.2.3.4";
- String remoteHost = this.remoteHost != null ? this.remoteHost : "remotehost";
- Integer remotePort = this.remotePort != null ? this.remotePort : 12345;
-
- HttpChannel channel = mock(HttpChannel.class);
- HttpConnection connection = mock(HttpConnection.class);
- JDiscServerConnector connector = mock(JDiscServerConnector.class);
- when(connector.connectorConfig()).thenReturn(new ConnectorConfig(new ConnectorConfig.Builder().listenPort(localPort)));
- when(connector.getLocalPort()).thenReturn(localPort);
- when(connection.getCreatedTimeStamp()).thenReturn(System.currentTimeMillis());
- when(connection.getConnector()).thenReturn(connector);
- when(connection.getHttpChannel()).thenReturn(channel);
- when(channel.getConnector()).thenReturn(connector);
- when(channel.getConnection()).thenReturn(connection);
-
- HttpInput httpInput = mock(HttpInput.class);
- when(httpInput.getContentReceived()).thenReturn(2345L);
-
- Request request = mock(Request.class);
- when(request.getHttpChannel()).thenReturn(channel);
- when(request.getHttpInput()).thenReturn(httpInput);
- when(request.getProtocol()).thenReturn("HTTP/1.1");
- when(request.getScheme()).thenReturn(scheme);
- when(request.getServerName()).thenReturn(serverName);
- when(request.getRemoteAddr()).thenReturn(remoteAddress);
- when(request.getRemotePort()).thenReturn(remotePort);
- when(request.getRemoteHost()).thenReturn(remoteHost);
- when(request.getLocalPort()).thenReturn(uriPort);
- when(request.getMethod()).thenReturn("GET");
- when(request.getQueryString()).thenReturn(query);
- when(request.getRequestURI()).thenReturn(path);
-
- mockCharacterEncodingHandling(request);
- mockHeaderHandling(request);
- mockParameterHandling(request);
- mockAttributeHandling(request);
-
- return request;
- }
-
- private void mockCharacterEncodingHandling(Request request) {
- try {
- AtomicReference<String> characterEncoding = new AtomicReference<>("");
- when(request.getCharacterEncoding()).thenAnswer((Answer<String>) ignored -> characterEncoding.get());
- doAnswer((Answer<Void>) invocation -> {
- String value = invocation.getArgument(0);
- characterEncoding.set(value);
- return null;
- }).when(request).setCharacterEncoding(anyString());
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void mockHeaderHandling(Request request) {
- Map<String, List<String>> headers = new ConcurrentHashMap<>(this.headers);
- when(request.getHeaderNames()).thenReturn(Collections.enumeration(headers.keySet()));
- when(request.getHeaders(anyString())).thenAnswer((Answer<Enumeration<String>>) invocation -> {
- String key = invocation.getArgument(0);
- List<String> values = headers.get(key);
- return values != null ? Collections.enumeration(values) : Collections.enumeration(List.of());
- });
- when(request.getHeader(anyString())).thenAnswer((Answer<String>) invocation -> {
- String name = invocation.getArgument(0);
- List<String> values = headers.get(name);
- if (values == null || values.isEmpty()) return null;
- return values.get(0);
- });
- }
-
- private void mockParameterHandling(Request request) {
- Map<String, String[]> parameters = new ConcurrentHashMap<>();
- this.parameters.forEach((key, values) -> parameters.put(key, values.toArray(String[]::new)));
- when(request.getParameterMap()).thenReturn(parameters);
- }
-
- private void mockAttributeHandling(Request request) {
- Map<String, Object> attributes = new ConcurrentHashMap<>(this.attributes);
-
- when(request.getAttribute(any())).thenAnswer(invocation -> {
- String attributeName = invocation.getArgument(0);
- return attributes.get(attributeName);
- });
- doAnswer((Answer<Void>) invocation -> {
- String attributeName = invocation.getArgument(0);
- Object attributeValue = invocation.getArgument(1);
- attributes.put(attributeName, attributeValue);
- return null;
- }).when(request).setAttribute(anyString(), any());
- doAnswer((Answer<Void>) invocation -> {
- String attributeName = invocation.getArgument(0);
- attributes.remove(attributeName);
- return null;
- }).when(request).removeAttribute(anyString());
- }
-}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockResponseBuilder.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockResponseBuilder.java
deleted file mode 100644
index 6addb966208..00000000000
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/JettyMockResponseBuilder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.jdisc.http.server.jetty;
-
-import org.eclipse.jetty.http.MetaData;
-import org.eclipse.jetty.server.HttpChannel;
-import org.eclipse.jetty.server.Response;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-/**
- * Builder for creating a mock instance of Jetty's {@link Response} type.
- *
- * @author bjorncs
- */
-public class JettyMockResponseBuilder {
-
- private JettyMockResponseBuilder() {}
-
- public static JettyMockResponseBuilder newBuilder() { return new JettyMockResponseBuilder(); }
-
- public Response build() {
- Response response = mock(Response.class);
- when(response.getHttpChannel()).thenReturn(mock(HttpChannel.class));
- when(response.getCommittedMetaData()).thenReturn(mock(MetaData.Response.class));
- return response;
- }
-
-}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java
index 161f48d847d..eea8d7e3072 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/SimpleHttpClient.java
@@ -1,36 +1,33 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.http.server.jetty;
-import org.apache.hc.client5.http.SystemDefaultDnsResolver;
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.classic.methods.HttpPost;
-import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
-import org.apache.hc.client5.http.entity.GzipCompressingEntity;
-import org.apache.hc.client5.http.entity.mime.FormBodyPart;
-import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
-import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
-import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
-import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
-import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;
-import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
-import org.apache.hc.core5.http.ContentType;
-import org.apache.hc.core5.http.Header;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.HttpResponse;
-import org.apache.hc.core5.http.ParseException;
-import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
-import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.entity.GzipCompressingEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.FormBodyPart;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.util.EntityUtils;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import javax.net.ssl.SSLContext;
import java.io.IOException;
-import java.net.InetAddress;
import java.net.URI;
-import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
@@ -58,9 +55,8 @@ public class SimpleHttpClient implements AutoCloseable {
public SimpleHttpClient(SSLContext sslContext, List<String> enabledProtocols, List<String> enabledCiphers,
int listenPort, boolean useCompression) {
- HttpClientBuilder builder = HttpClientBuilder.create()
- .disableAutomaticRetries()
- .disableConnectionState(); // Reuse SSL connection when client authentication is enabled
+ HttpClientBuilder builder = HttpClientBuilder.create();
+ builder.disableConnectionState(); // Reuse SSL connection when client authentication is enabled
if (!useCompression) {
builder.disableContentCompression();
}
@@ -70,17 +66,12 @@ public class SimpleHttpClient implements AutoCloseable {
toArray(enabledProtocols),
toArray(enabledCiphers),
new DefaultHostnameVerifier());
- PoolingHttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create()
- .setSSLSocketFactory(sslConnectionFactory)
- .setDnsResolver(new SystemDefaultDnsResolver() {
- @Override
- public InetAddress[] resolve(String host) throws UnknownHostException {
- // Returns single address instead of multiple (to avoid multiple connection attempts)
- return new InetAddress[] { InetAddress.getByName(host) };
- }
- })
+ builder.setSSLSocketFactory(sslConnectionFactory);
+
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+ .register("https", sslConnectionFactory)
.build();
- builder.setConnectionManager(connManager);
+ builder.setConnectionManager(new BasicHttpClientConnectionManager(registry));
scheme = "https";
} else {
scheme = "http";
@@ -148,7 +139,7 @@ public class SimpleHttpClient implements AutoCloseable {
}
public RequestExecutor setBinaryContent(final byte[] content) {
- this.entity = new ByteArrayEntity(content, ContentType.DEFAULT_BINARY);
+ this.entity = new ByteArrayEntity(content);
return this;
}
@@ -161,7 +152,7 @@ public class SimpleHttpClient implements AutoCloseable {
public ResponseValidator execute() throws IOException {
if (entity != null) {
- request.setEntity(entity);
+ ((HttpPost)request).setEntity(entity);
}
try (CloseableHttpResponse response = delegate.execute(request)){
return new ResponseValidator(response);
@@ -174,19 +165,15 @@ public class SimpleHttpClient implements AutoCloseable {
private final HttpResponse response;
private final String content;
- public ResponseValidator(CloseableHttpResponse response) throws IOException {
- try {
- this.response = response;
+ public ResponseValidator(HttpResponse response) throws IOException {
+ this.response = response;
- HttpEntity entity = response.getEntity();
- this.content = entity == null ? null : EntityUtils.toString(entity, StandardCharsets.UTF_8);
- } catch (ParseException e) {
- throw new IOException(e);
- }
+ HttpEntity entity = response.getEntity();
+ this.content = entity == null ? null : EntityUtils.toString(entity, StandardCharsets.UTF_8);
}
public ResponseValidator expectStatusCode(Matcher<Integer> matcher) {
- MatcherAssert.assertThat(response.getCode(), matcher);
+ MatcherAssert.assertThat(response.getStatusLine().getStatusCode(), matcher);
return this;
}
diff --git a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/TestDrivers.java b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/TestDrivers.java
index 75fc0948da9..7d7530c32e0 100644
--- a/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/TestDrivers.java
+++ b/container-core/src/test/java/com/yahoo/jdisc/http/server/jetty/TestDrivers.java
@@ -55,7 +55,10 @@ public class TestDrivers {
newConfigModule(
new ServerConfig.Builder().connectionLog(new ServerConfig.ConnectionLog.Builder().enabled(true)),
new ConnectorConfig.Builder()
- .http2Enabled(true)
+ .tlsClientAuthEnforcer(
+ new ConnectorConfig.TlsClientAuthEnforcer.Builder()
+ .enable(true)
+ .pathWhitelist("/status.html"))
.ssl(new ConnectorConfig.Ssl.Builder()
.enabled(true)
.clientAuth(tlsClientAuth == TlsClientAuth.NEED