From cbc3ac01f244f34d25d3e88e74e4bbf3d9dbff76 Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Wed, 18 Sep 2024 17:42:21 +0200 Subject: [PATCH 1/2] #11841 add reproducer using jetty client Signed-off-by: Ludovic Orban --- .../ee10/proxy/AsyncMiddleManServletTest.java | 31 ++++++++++++++++--- .../ee9/proxy/AsyncMiddleManServletTest.java | 26 ++++++++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java index c1218587ab0b..b32b99487ad6 100644 --- a/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java +++ b/jetty-ee10/jetty-ee10-proxy/src/test/java/org/eclipse/jetty/ee10/proxy/AsyncMiddleManServletTest.java @@ -61,6 +61,7 @@ import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.StringRequestContent; import org.eclipse.jetty.ee10.servlet.ServletContextHandler; import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.eclipse.jetty.http.HttpHeader; @@ -79,6 +80,7 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.ajax.JSON; +import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -163,11 +165,32 @@ private void startClient() throws Exception } @AfterEach - public void dispose() throws Exception + public void dispose() { - client.stop(); - proxy.stop(); - server.stop(); + LifeCycle.stop(client); + LifeCycle.stop(proxy); + LifeCycle.stop(server); + } + + @Test + public void testExpect100WithBody() throws Exception + { + startServer(new EchoHttpServlet()); + startProxy(new AsyncMiddleManServlet()); + startClient(); + + for (int i = 0; i < 100; i++) + { + String body = Character.toString('a' + (i % 26)); // only use 'a' to 'z' + ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort()) + .path("/" + body) + .headers(h -> h.put(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE)) + .timeout(5, TimeUnit.SECONDS) + .body(new StringRequestContent(body)) + .send(); + assertEquals(200, response.getStatus()); + assertEquals(body, response.getContentAsString()); + } } @Test diff --git a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java index 064ac6687455..433e59a41f2c 100644 --- a/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java +++ b/jetty-ee9/jetty-ee9-proxy/src/test/java/org/eclipse/jetty/ee9/proxy/AsyncMiddleManServletTest.java @@ -61,6 +61,7 @@ import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.StringRequestContent; import org.eclipse.jetty.ee9.servlet.ServletContextHandler; import org.eclipse.jetty.ee9.servlet.ServletHolder; import org.eclipse.jetty.http.HttpHeader; @@ -163,11 +164,32 @@ private void startClient() throws Exception } @AfterEach - public void dispose() throws Exception + public void dispose() { LifeCycle.stop(client); LifeCycle.stop(proxy); - LifeCycle.stop(proxy); + LifeCycle.stop(server); + } + + @Test + public void testExpect100WithBody() throws Exception + { + startServer(new EchoHttpServlet()); + startProxy(new AsyncMiddleManServlet()); + startClient(); + + for (int i = 0; i < 100; i++) + { + String body = Character.toString('a' + (i % 26)); // only use 'a' to 'z' + ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort()) + .path("/" + body) + .headers(h -> h.put(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE)) + .timeout(5, TimeUnit.SECONDS) + .body(new StringRequestContent(body)) + .send(); + assertEquals(200, response.getStatus()); + assertEquals(body, response.getContentAsString()); + } } @Test From 1d9f10871ad9c1016d28f0d1fee9fc6089c85188 Mon Sep 17 00:00:00 2001 From: Niklas Keller Date: Tue, 24 Sep 2024 06:40:16 +0200 Subject: [PATCH 2/2] Issue #12047 allow disabling opening connectors before starting (#12049) --- .../java/org/eclipse/jetty/server/Server.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 166c70b0952b..222d7f74f14c 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -86,6 +86,7 @@ public class Server extends Handler.Wrapper implements Attributes private final AutoLock _dateLock = new AutoLock(); private final MimeTypes.Mutable _mimeTypes = new MimeTypes.Mutable(); private String _serverInfo = __serverInfo; + private boolean _openEarly = true; private boolean _stopAtShutdown; private boolean _dumpAfterStart; private boolean _dumpBeforeStop; @@ -276,6 +277,22 @@ public InvocationType getInvocationType() return type; } + public boolean isOpenEarly() + { + return _openEarly; + } + + /** + * Allows to disable early opening of network sockets. Network sockets are opened early by default. + * @param openEarly If {@code openEarly} is {@code true} (default), network sockets are opened before + * starting other components. If {@code openEarly} is {@code false}, network connectors open sockets + * when they're started. + */ + public void setOpenEarly(boolean openEarly) + { + _openEarly = openEarly; + } + public boolean isDryRun() { return _dryRun; @@ -543,7 +560,7 @@ protected void doStart() throws Exception final ExceptionUtil.MultiException multiException = new ExceptionUtil.MultiException(); // Open network connector to ensure ports are available - if (!_dryRun) + if (!_dryRun && _openEarly) { _connectors.stream().filter(NetworkConnector.class::isInstance).map(NetworkConnector.class::cast).forEach(connector -> {