From a9d391079ccc39db8f9ab12b6fa4e7da94235673 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 21 Aug 2024 23:42:50 +1000 Subject: [PATCH 1/7] implement servlet upgrade for ee10 and ee11 Signed-off-by: Lachlan Roberts --- .../org/eclipse/jetty/http/HttpParser.java | 4 +- .../jetty/http2/tests/HTTP2CServerTest.java | 2 +- .../jetty/server/AbstractConnector.java | 1 - .../server/ForwardedRequestCustomizer.java | 1 - .../server/{internal => }/HttpConnection.java | 13 +- .../jetty/server/HttpConnectionFactory.java | 1 - .../jetty/server/DelayedServerTest.java | 1 - .../jetty/server/ExtendedServerTest.java | 1 - .../ForwardedRequestCustomizerTest.java | 1 - .../jetty/server/HttpConnectionTest.java | 1 - .../jetty/server/HttpServerTestBase.java | 1 - .../jetty/server/ResponseCompleteTest.java | 1 - .../org/eclipse/jetty/server/ServerTest.java | 1 - .../SlowClientWithPipelinedRequestTest.java | 1 - .../org/eclipse/jetty/server/StopTest.java | 1 - .../server/handler/DelayedHandlerTest.java | 4 +- .../ssl/SniSslConnectionFactoryTest.java | 4 +- .../server/ssl/SslConnectionFactoryTest.java | 4 +- .../client/transport/ConnectionPoolTest.java | 2 +- .../jetty/ee10/servlet/ServletApiRequest.java | 258 +++++++++++++++++- .../util/ServletInputStreamWrapper.java | 114 ++++++++ .../util/ServletOutputStreamWrapper.java | 96 ------- .../ee10/servlet/ServletUpgradeTest.java | 229 +++++----------- .../ee10/test/GzipWithSendErrorTest.java | 2 +- .../jetty/ee11/servlet/ServletApiRequest.java | 258 +++++++++++++++++- .../util/ServletInputStreamWrapper.java | 131 +++++++++ .../ee11/servlet/ServletUpgradeTest.java | 229 +++++----------- .../ee11/test/GzipWithSendErrorTest.java | 2 +- .../jetty/ee9/test/GzipWithSendErrorTest.java | 3 +- 29 files changed, 912 insertions(+), 455 deletions(-) rename jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/{internal => }/HttpConnection.java (99%) create mode 100644 jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletInputStreamWrapper.java create mode 100644 jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 93be3478cb01..5198f28db74e 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -2018,8 +2018,8 @@ public void reset() public void servletUpgrade() { - setState(State.CONTENT); - _endOfContent = EndOfContent.UNKNOWN_CONTENT; + setState(State.EOF_CONTENT); + _endOfContent = EndOfContent.EOF_CONTENT; _contentLength = -1; } diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java index 13617566c882..3d61be8aa01e 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java @@ -42,9 +42,9 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.Utf8StringBuilder; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index 5be4f03d2a35..72391323943f 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -37,7 +37,6 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.io.ssl.SslConnection; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.ProcessorUtils; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index eddb9f7cfcff..3237c6486732 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.QuotedCSVParser; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.Index; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java similarity index 99% rename from jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java rename to jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 2027b6542fc0..6afb55a760c4 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -11,7 +11,7 @@ // ======================================================================== // -package org.eclipse.jetty.server.internal; +package org.eclipse.jetty.server; import java.io.IOException; import java.nio.ByteBuffer; @@ -53,16 +53,7 @@ import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.ssl.SslConnection; -import org.eclipse.jetty.server.AbstractMetaDataConnection; -import org.eclipse.jetty.server.ConnectionFactory; -import org.eclipse.jetty.server.ConnectionMetaData; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpChannel; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpStream; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.TunnelSupport; +import org.eclipse.jetty.server.internal.HttpChannelState; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.HostPort; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java index 30b5d9b5067a..502131b53b98 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java @@ -19,7 +19,6 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.annotation.Name; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java index 3a1ec920d762..d20abd8cb279 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java @@ -19,7 +19,6 @@ import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.BeforeEach; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java index 7d9aa6812f80..67ac2eaae950 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java @@ -25,7 +25,6 @@ import org.eclipse.jetty.io.ManagedSelector; import org.eclipse.jetty.io.SocketChannelEndPoint; import org.eclipse.jetty.server.internal.HttpChannelState; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.NanoTime; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java index 2b8b97036a4d..ae588464a39c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index b93a6daa100f..fc078af5030d 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -46,7 +46,6 @@ import org.eclipse.jetty.io.Content; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.handler.DumpHandler; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.NanoTime; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index 8f1c60271b1a..77c18c6f3bd4 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -48,7 +48,6 @@ import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.handler.EchoHandler; import org.eclipse.jetty.server.handler.HelloHandler; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java index 482cfe2a1e5c..4a9619cd358c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.logging.StacklessLogging; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.component.LifeCycle; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java index dcca3eb0375a..dccc272d24dc 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.internal.HttpChannelState; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Jetty; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java index 12069ad7e157..959272f227b5 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java @@ -23,7 +23,6 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java index 48bcf7e9a61b..f044a2d62339 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java @@ -31,7 +31,6 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.StatisticsHandler; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.FutureCallback; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java index 88c213a3132d..4b0daad89863 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java @@ -298,7 +298,7 @@ public boolean handle(Request request, Response response, Callback callback) thr ByteArrayOutputStream out = new ByteArrayOutputStream(8192); new Throwable().printStackTrace(new PrintStream(out)); String stack = out.toString(StandardCharsets.ISO_8859_1); - assertThat(stack, containsString("org.eclipse.jetty.server.internal.HttpConnection.onFillable")); + assertThat(stack, containsString("org.eclipse.jetty.server.HttpConnection.onFillable")); assertThat(stack, containsString("org.eclipse.jetty.server.handler.DelayedHandler.handle")); // Check the content is available @@ -469,7 +469,7 @@ public boolean handle(Request request, Response response, Callback callback) thr ByteArrayOutputStream out = new ByteArrayOutputStream(8192); new Throwable().printStackTrace(new PrintStream(out)); String stack = out.toString(StandardCharsets.ISO_8859_1); - assertThat(stack, containsString("org.eclipse.jetty.server.internal.HttpConnection.onFillable")); + assertThat(stack, containsString("org.eclipse.jetty.server.HttpConnection.onFillable")); assertThat(stack, containsString("org.eclipse.jetty.server.handler.DelayedHandler.handle")); Fields fields = FormFields.from(request).get(1, TimeUnit.NANOSECONDS); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java index 46784e2434ec..d833123926b3 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java @@ -494,8 +494,8 @@ protected void customize(Socket socket, Class connection, assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); - assertEquals("customize connector class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); - assertEquals("customize http class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); + assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true", history.poll()); + assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true", history.poll()); assertEquals(0, history.size()); } diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java index ebe49e17e0e1..04f4aef7305c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java @@ -178,8 +178,8 @@ protected void customize(Socket socket, Class connection, assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); - assertEquals("customize connector class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); - assertEquals("customize http class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); + assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true", history.poll()); + assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true", history.poll()); assertEquals(0, history.size()); } diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java index a634883faea3..1f2c4ee6092b 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java @@ -24,7 +24,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.quic.server.ServerQuicConnection; -import org.eclipse.jetty.server.internal.HttpConnection; +import org.eclipse.jetty.server.HttpConnection; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java index 38e93d25c1d2..63095e87b1c1 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java @@ -41,15 +41,18 @@ import jakarta.servlet.AsyncContext; import jakarta.servlet.DispatcherType; +import jakarta.servlet.ReadListener; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletConnection; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletOutputStream; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequestAttributeEvent; import jakarta.servlet.ServletRequestAttributeListener; import jakarta.servlet.ServletResponse; +import jakarta.servlet.WriteListener; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletMapping; import jakarta.servlet.http.HttpServletRequest; @@ -58,7 +61,10 @@ import jakarta.servlet.http.HttpUpgradeHandler; import jakarta.servlet.http.Part; import jakarta.servlet.http.PushBuilder; +import jakarta.servlet.http.WebConnection; import org.eclipse.jetty.ee10.servlet.ServletContextHandler.ServletRequestInfo; +import org.eclipse.jetty.ee10.servlet.util.ServletInputStreamWrapper; +import org.eclipse.jetty.ee10.servlet.util.ServletOutputStreamWrapper; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpCookie; @@ -79,6 +85,7 @@ import org.eclipse.jetty.server.ConnectionMetaData; import org.eclipse.jetty.server.CookieCache; import org.eclipse.jetty.server.FormFields; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -737,8 +744,250 @@ public Part getPart(String name) throws IOException, ServletException @Override public T upgrade(Class handlerClass) throws IOException, ServletException { - // Not implemented. Throw ServletException as per spec. - throw new ServletException("Not implemented"); + Response response = _servletContextRequest.getServletContextResponse(); + if (response.getStatus() != HttpStatus.SWITCHING_PROTOCOLS_101) + throw new IllegalStateException("Response status should be 101"); + if (response.getHeaders().get("Upgrade") == null) + throw new IllegalStateException("Missing Upgrade header"); + if (!"Upgrade".equalsIgnoreCase(response.getHeaders().get("Connection"))) + throw new IllegalStateException("Invalid Connection header"); + if (response.isCommitted()) + throw new IllegalStateException("Cannot upgrade committed response"); + if (_servletChannel.getConnectionMetaData().getHttpVersion() != HttpVersion.HTTP_1_1) + throw new IllegalStateException("Only requests over HTTP/1.1 can be upgraded"); + + CompletableFuture outputStreamComplete = new CompletableFuture<>(); + CompletableFuture inputStreamComplete = new CompletableFuture<>(); + ServletOutputStream outputStream = new ServletOutputStreamWrapper(_servletContextRequest.getHttpOutput()) + { + @Override + public void write(int b) throws IOException + { + try + { + super.write(b); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void write(byte[] b) throws IOException + { + try + { + super.write(b); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException + { + try + { + super.write(b, off, len); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void close() throws IOException + { + try + { + super.close(); + outputStreamComplete.complete(null); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void setWriteListener(WriteListener writeListener) + { + super.setWriteListener(new WriteListener() + { + @Override + public void onWritePossible() throws IOException + { + writeListener.onWritePossible(); + } + + @Override + public void onError(Throwable t) + { + writeListener.onError(t); + outputStreamComplete.completeExceptionally(t); + } + }); + } + }; + ServletInputStream inputStream = new ServletInputStreamWrapper(_servletContextRequest.getHttpInput()) + { + @Override + public int read() throws IOException + { + try + { + int read = super.read(); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public int read(byte[] b) throws IOException + { + try + { + int read = super.read(b); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + try + { + int read = super.read(b, off, len); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void close() throws IOException + { + try + { + super.close(); + inputStreamComplete.complete(null); + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void setReadListener(ReadListener readListener) + { + super.setReadListener(new ReadListener() + { + @Override + public void onDataAvailable() throws IOException + { + readListener.onDataAvailable(); + } + + @Override + public void onAllDataRead() throws IOException + { + try + { + readListener.onAllDataRead(); + inputStreamComplete.complete(null); + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void onError(Throwable t) + { + readListener.onError(t); + inputStreamComplete.completeExceptionally(t); + } + }); + } + }; + + T upgradeHandler; + try + { + upgradeHandler = handlerClass.getDeclaredConstructor().newInstance(); + } + catch (Exception e) + { + throw new ServletException("Unable to instantiate handler class", e); + } + + HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); + httpConnection.getParser().servletUpgrade(); + AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode + + outputStream.flush(); // commit the 101 response + httpConnection.getGenerator().servletUpgrade(); // tell the generator it can send data as-is + + CompletableFuture.allOf(inputStreamComplete, outputStreamComplete).whenComplete((result, failure) -> + { + upgradeHandler.destroy(); + asyncContext.complete(); + }); + + WebConnection webConnection = new WebConnection() + { + @Override + public void close() throws Exception + { + IO.close(inputStream); + IO.close(outputStream); + } + + @Override + public ServletInputStream getInputStream() + { + return inputStream; + } + + @Override + public ServletOutputStream getOutputStream() + { + return outputStream; + } + }; + + upgradeHandler.init(webConnection); + return upgradeHandler; } @Override @@ -1374,6 +1623,11 @@ public AsyncContext startAsync() throws IllegalStateException { if (!isAsyncSupported()) throw new IllegalStateException("Async Not Supported"); + return forceStartAsync(); + } + + private AsyncContext forceStartAsync() + { ServletChannelState state = getServletRequestInfo().getState(); if (_async == null) _async = new AsyncContextState(state); diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletInputStreamWrapper.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletInputStreamWrapper.java new file mode 100644 index 000000000000..f2c033944ed3 --- /dev/null +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletInputStreamWrapper.java @@ -0,0 +1,114 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.ee10.servlet.util; + +import java.io.IOException; +import java.io.OutputStream; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; + +public class ServletInputStreamWrapper extends ServletInputStream +{ + private final ServletInputStream _servletInputStream; + + public ServletInputStreamWrapper(ServletInputStream servletInputStream) + { + _servletInputStream = servletInputStream; + } + + @Override + public boolean isFinished() + { + return _servletInputStream.isFinished(); + } + + @Override + public boolean isReady() + { + return _servletInputStream.isReady(); + } + + @Override + public void setReadListener(ReadListener readListener) + { + _servletInputStream.setReadListener(readListener); + } + + @Override + public int read() throws IOException + { + return _servletInputStream.read(); + } + + @Override + public int read(byte[] b) throws IOException + { + return _servletInputStream.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + return _servletInputStream.read(b, off, len); + } + + @Override + public long skip(long n) throws IOException + { + return _servletInputStream.skip(n); + } + + @Override + public void skipNBytes(long n) throws IOException + { + _servletInputStream.skipNBytes(n); + } + + @Override + public int available() throws IOException + { + return _servletInputStream.available(); + } + + @Override + public void close() throws IOException + { + _servletInputStream.close(); + } + + @Override + public void mark(int readlimit) + { + _servletInputStream.mark(readlimit); + } + + @Override + public void reset() throws IOException + { + _servletInputStream.reset(); + } + + @Override + public boolean markSupported() + { + return _servletInputStream.markSupported(); + } + + @Override + public long transferTo(OutputStream out) throws IOException + { + return _servletInputStream.transferTo(out); + } +} diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletOutputStreamWrapper.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletOutputStreamWrapper.java index def8070f40f4..696b1576a0e5 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletOutputStreamWrapper.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/util/ServletOutputStreamWrapper.java @@ -14,7 +14,6 @@ package org.eclipse.jetty.ee10.servlet.util; import java.io.IOException; -import java.io.OutputStream; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; @@ -28,96 +27,6 @@ public ServletOutputStreamWrapper(ServletOutputStream outputStream) _outputStream = outputStream; } - @Override - public void print(String s) throws IOException - { - _outputStream.print(s); - } - - @Override - public void print(boolean b) throws IOException - { - _outputStream.print(b); - } - - @Override - public void print(char c) throws IOException - { - _outputStream.print(c); - } - - @Override - public void print(int i) throws IOException - { - _outputStream.print(i); - } - - @Override - public void print(long l) throws IOException - { - _outputStream.print(l); - } - - @Override - public void print(float f) throws IOException - { - _outputStream.print(f); - } - - @Override - public void print(double d) throws IOException - { - _outputStream.print(d); - } - - @Override - public void println() throws IOException - { - _outputStream.println(); - } - - @Override - public void println(String s) throws IOException - { - _outputStream.println(s); - } - - @Override - public void println(boolean b) throws IOException - { - _outputStream.println(b); - } - - @Override - public void println(char c) throws IOException - { - _outputStream.println(c); - } - - @Override - public void println(int i) throws IOException - { - _outputStream.println(i); - } - - @Override - public void println(long l) throws IOException - { - _outputStream.println(l); - } - - @Override - public void println(float f) throws IOException - { - _outputStream.println(f); - } - - @Override - public void println(double d) throws IOException - { - _outputStream.println(d); - } - @Override public boolean isReady() { @@ -130,11 +39,6 @@ public void setWriteListener(WriteListener writeListener) _outputStream.setWriteListener(writeListener); } - public static OutputStream nullOutputStream() - { - return OutputStream.nullOutputStream(); - } - @Override public void write(int b) throws IOException { diff --git a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ServletUpgradeTest.java b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ServletUpgradeTest.java index 8fd6a338b95f..49b7076e36a8 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ServletUpgradeTest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/ServletUpgradeTest.java @@ -17,6 +17,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletException; @@ -29,16 +32,18 @@ import jakarta.servlet.http.WebConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.Utf8StringBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.eclipse.jetty.util.StringUtil.CRLF; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertTrue; public class ServletUpgradeTest @@ -47,10 +52,13 @@ public class ServletUpgradeTest private Server server; private int port; + private static CountDownLatch destroyLatch; @BeforeEach public void setUp() throws Exception { + destroyLatch = new CountDownLatch(1); + server = new Server(); ServerConnector connector = new ServerConnector(server); @@ -72,130 +80,64 @@ public void tearDown() throws Exception server.stop(); } - @Disabled @Test public void upgradeTest() throws Exception { - boolean passed1 = false; - boolean passed2 = false; - boolean passed3 = false; - String expectedResponse1 = "TCKHttpUpgradeHandler.init"; - String expectedResponse2 = "onDataAvailable|Hello"; - String expectedResponse3 = "onDataAvailable|World"; - - InputStream input = null; - OutputStream output = null; - Socket s = null; - - try + Socket socket = new Socket("localhost", port); + socket.setSoTimeout(0); + InputStream input = socket.getInputStream(); + OutputStream output = socket.getOutputStream(); + + String request = "POST /TestServlet HTTP/1.1" + CRLF + + "Host: localhost:" + port + CRLF + + "Upgrade: YES" + CRLF + + "Connection: Upgrade" + CRLF + + CRLF; + + output.write(request.getBytes()); + writeChunk(output, "Hello"); + writeChunk(output, "World"); + output.flush(); + socket.shutdownOutput(); + + CompletableFuture futureContent = new CompletableFuture<>(); + new Thread(() -> { - s = new Socket("localhost", port); - output = s.getOutputStream(); - - StringBuilder reqStr = new StringBuilder() - .append("POST /TestServlet HTTP/1.1").append(CRLF) - .append("User-Agent: Java/1.6.0_33").append(CRLF) - .append("Host: localhost:").append(port).append(CRLF) - .append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2").append(CRLF) - .append("Upgrade: YES").append(CRLF) - .append("Connection: Upgrade").append(CRLF) - .append("Content-type: application/x-www-form-urlencoded").append(CRLF) - .append(CRLF); - - LOG.info("REQUEST=========" + reqStr.toString()); - output.write(reqStr.toString().getBytes()); - - LOG.info("Writing first chunk"); - writeChunk(output, "Hello"); - - LOG.info("Writing second chunk"); - writeChunk(output, "World"); - LOG.info("Consuming the response from the server"); - - // Consume the response from the server - input = s.getInputStream(); - int len; - byte[] b = new byte[1024]; - boolean receivedFirstMessage = false; - boolean receivedSecondMessage = false; - boolean receivedThirdMessage = false; - StringBuilder sb = new StringBuilder(); - while ((len = input.read(b)) != -1) - { - String line = new String(b, 0, len); - sb.append(line); - LOG.info("==============Read from server:" + CRLF + sb + CRLF); - if (passed1 = compareString(expectedResponse1, sb.toString())) - { - LOG.info("==============Received first expected response!" + CRLF); - receivedFirstMessage = true; - } - if (passed2 = compareString(expectedResponse2, sb.toString())) - { - LOG.info("==============Received second expected response!" + CRLF); - receivedSecondMessage = true; - } - if (passed3 = compareString(expectedResponse3, sb.toString())) - { - LOG.info("==============Received third expected response!" + CRLF); - receivedThirdMessage = true; - } - LOG.info("receivedFirstMessage : " + receivedFirstMessage); - LOG.info("receivedSecondMessage : " + receivedSecondMessage); - LOG.info("receivedThirdMessage : " + receivedThirdMessage); - if (receivedFirstMessage && receivedSecondMessage && receivedThirdMessage) - { - break; - } - } - } - finally - { + Utf8StringBuilder sb = new Utf8StringBuilder(); try { - if (input != null) + while (true) { - LOG.info("Closing input..."); - input.close(); - LOG.info("Input closed."); + int read = input.read(); + if (read == -1) + break; + sb.append((byte)read); } + futureContent.complete(sb.toCompleteString()); } - catch (Exception ex) + catch (Throwable t) { - LOG.error("Failed to close input:" + ex.getMessage(), ex); + LOG.warn("failed with content: " + sb, t); + futureContent.completeExceptionally(t); } - try - { - if (output != null) - { - LOG.info("Closing output..."); - output.close(); - LOG.info("Output closed ."); - } - } - catch (Exception ex) - { - LOG.error("Failed to close output:" + ex.getMessage(), ex); - } - - try - { - if (s != null) - { - LOG.info("Closing socket..." + CRLF); - s.close(); - LOG.info("Socked closed."); - } - } - catch (Exception ex) - { - LOG.error("Failed to close socket:" + ex.getMessage(), ex); - } - } - - assertTrue(passed1 && passed2 && passed3); + }).start(); + + String content = futureContent.get(5, TimeUnit.SECONDS); + String expectedContent = """ + TCKHttpUpgradeHandler.init\r + =onDataAvailable\r + HelloWorld\r + =onAllDataRead\r + """; + assertThat(content, startsWith("HTTP/1.1 101 Switching Protocols")); + assertThat(content, endsWith(expectedContent)); + + input.close(); + output.close(); + socket.close(); + assertTrue(destroyLatch.await(5, TimeUnit.SECONDS)); } private static class TestServlet extends HttpServlet @@ -227,7 +169,7 @@ public TestHttpUpgradeHandler() @Override public void destroy() { - LOG.debug("===============destroy"); + destroyLatch.countDown(); } @Override @@ -237,9 +179,9 @@ public void init(WebConnection wc) { ServletInputStream input = wc.getInputStream(); ServletOutputStream output = wc.getOutputStream(); - TestReadListener readListener = new TestReadListener("/", input, output); + TestReadListener readListener = new TestReadListener(input, output); input.setReadListener(readListener); - output.println("===============TCKHttpUpgradeHandler.init"); + output.println("TCKHttpUpgradeHandler.init"); output.flush(); } catch (Exception ex) @@ -253,20 +195,20 @@ private static class TestReadListener implements ReadListener { private final ServletInputStream input; private final ServletOutputStream output; - private final String delimiter; + private boolean outputOnDataAvailable = false; - TestReadListener(String del, ServletInputStream in, ServletOutputStream out) + TestReadListener(ServletInputStream in, ServletOutputStream out) { input = in; output = out; - delimiter = del; } + @Override public void onAllDataRead() { try { - output.println("=onAllDataRead"); + output.println("\r\n=onAllDataRead"); output.close(); } catch (Exception ex) @@ -275,11 +217,17 @@ public void onAllDataRead() } } + @Override public void onDataAvailable() { try { - output.println("=onDataAvailable"); + if (!outputOnDataAvailable) + { + outputOnDataAvailable = true; + output.println("=onDataAvailable"); + } + StringBuilder sb = new StringBuilder(); int len; byte[] b = new byte[1024]; @@ -288,7 +236,7 @@ public void onDataAvailable() String data = new String(b, 0, len); sb.append(data); } - output.println(delimiter + sb.toString()); + output.print(sb.toString()); output.flush(); } catch (Exception ex) @@ -297,50 +245,13 @@ public void onDataAvailable() } } + @Override public void onError(final Throwable t) { LOG.error("TestReadListener error", t); } } - private static boolean compareString(String expected, String actual) - { - String[] listExpected = expected.split("[|]"); - boolean found = true; - for (int i = 0, n = listExpected.length, startIdx = 0, bodyLength = actual.length(); i < n; i++) - { - String search = listExpected[i]; - if (startIdx >= bodyLength) - { - startIdx = bodyLength; - } - - int searchIdx = actual.toLowerCase().indexOf(search.toLowerCase(), startIdx); - - LOG.debug("[ServletTestUtil] Scanning response for " + "search string: '" + search + "' starting at index " + "location: " + startIdx); - if (searchIdx < 0) - { - found = false; - String s = "[ServletTestUtil] Unable to find the following " + - "search string in the server's " + - "response: '" + search + "' at index: " + - startIdx + - "\n[ServletTestUtil] Server's response:\n" + - "-------------------------------------------\n" + - actual + - "\n-------------------------------------------\n"; - LOG.debug(s); - break; - } - - LOG.debug("[ServletTestUtil] Found search string: '" + search + "' at index '" + searchIdx + "' in the server's " + "response"); - // the new searchIdx is the old index plus the lenght of the - // search string. - startIdx = searchIdx + search.length(); - } - return found; - } - private static void writeChunk(OutputStream out, String data) throws IOException { if (data != null) diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java index 67c5bfb08e47..63d851f604d9 100644 --- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java @@ -44,10 +44,10 @@ import org.eclipse.jetty.ee10.servlet.ServletContextRequest; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java index 1981b89a8741..0ad597cc3581 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java @@ -41,15 +41,18 @@ import jakarta.servlet.AsyncContext; import jakarta.servlet.DispatcherType; +import jakarta.servlet.ReadListener; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletConnection; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletOutputStream; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequestAttributeEvent; import jakarta.servlet.ServletRequestAttributeListener; import jakarta.servlet.ServletResponse; +import jakarta.servlet.WriteListener; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletMapping; import jakarta.servlet.http.HttpServletRequest; @@ -58,7 +61,10 @@ import jakarta.servlet.http.HttpUpgradeHandler; import jakarta.servlet.http.Part; import jakarta.servlet.http.PushBuilder; +import jakarta.servlet.http.WebConnection; import org.eclipse.jetty.ee11.servlet.ServletContextHandler.ServletRequestInfo; +import org.eclipse.jetty.ee11.servlet.util.ServletInputStreamWrapper; +import org.eclipse.jetty.ee11.servlet.util.ServletOutputStreamWrapper; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.CookieCompliance; import org.eclipse.jetty.http.HttpCookie; @@ -79,6 +85,7 @@ import org.eclipse.jetty.server.ConnectionMetaData; import org.eclipse.jetty.server.CookieCache; import org.eclipse.jetty.server.FormFields; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -737,8 +744,250 @@ public Part getPart(String name) throws IOException, ServletException @Override public T upgrade(Class handlerClass) throws IOException, ServletException { - // Not implemented. Throw ServletException as per spec. - throw new ServletException("Not implemented"); + Response response = _servletContextRequest.getServletContextResponse(); + if (response.getStatus() != HttpStatus.SWITCHING_PROTOCOLS_101) + throw new IllegalStateException("Response status should be 101"); + if (response.getHeaders().get("Upgrade") == null) + throw new IllegalStateException("Missing Upgrade header"); + if (!"Upgrade".equalsIgnoreCase(response.getHeaders().get("Connection"))) + throw new IllegalStateException("Invalid Connection header"); + if (response.isCommitted()) + throw new IllegalStateException("Cannot upgrade committed response"); + if (_servletChannel.getConnectionMetaData().getHttpVersion() != HttpVersion.HTTP_1_1) + throw new IllegalStateException("Only requests over HTTP/1.1 can be upgraded"); + + CompletableFuture outputStreamComplete = new CompletableFuture<>(); + CompletableFuture inputStreamComplete = new CompletableFuture<>(); + ServletOutputStream outputStream = new ServletOutputStreamWrapper(_servletContextRequest.getHttpOutput()) + { + @Override + public void write(int b) throws IOException + { + try + { + super.write(b); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void write(byte[] b) throws IOException + { + try + { + super.write(b); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException + { + try + { + super.write(b, off, len); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void close() throws IOException + { + try + { + super.close(); + outputStreamComplete.complete(null); + } + catch (Throwable t) + { + outputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void setWriteListener(WriteListener writeListener) + { + super.setWriteListener(new WriteListener() + { + @Override + public void onWritePossible() throws IOException + { + writeListener.onWritePossible(); + } + + @Override + public void onError(Throwable t) + { + writeListener.onError(t); + outputStreamComplete.completeExceptionally(t); + } + }); + } + }; + ServletInputStream inputStream = new ServletInputStreamWrapper(_servletContextRequest.getHttpInput()) + { + @Override + public int read() throws IOException + { + try + { + int read = super.read(); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public int read(byte[] b) throws IOException + { + try + { + int read = super.read(b); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + try + { + int read = super.read(b, off, len); + if (read == -1) + inputStreamComplete.complete(null); + return read; + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void close() throws IOException + { + try + { + super.close(); + inputStreamComplete.complete(null); + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void setReadListener(ReadListener readListener) + { + super.setReadListener(new ReadListener() + { + @Override + public void onDataAvailable() throws IOException + { + readListener.onDataAvailable(); + } + + @Override + public void onAllDataRead() throws IOException + { + try + { + readListener.onAllDataRead(); + inputStreamComplete.complete(null); + } + catch (Throwable t) + { + inputStreamComplete.completeExceptionally(t); + throw t; + } + } + + @Override + public void onError(Throwable t) + { + readListener.onError(t); + inputStreamComplete.completeExceptionally(t); + } + }); + } + }; + + T upgradeHandler; + try + { + upgradeHandler = handlerClass.getDeclaredConstructor().newInstance(); + } + catch (Exception e) + { + throw new ServletException("Unable to instantiate handler class", e); + } + + HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); + httpConnection.getParser().servletUpgrade(); + AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode + + outputStream.flush(); // commit the 101 response + httpConnection.getGenerator().servletUpgrade(); // tell the generator it can send data as-is + + CompletableFuture.allOf(inputStreamComplete, outputStreamComplete).whenComplete((result, failure) -> + { + upgradeHandler.destroy(); + asyncContext.complete(); + }); + + WebConnection webConnection = new WebConnection() + { + @Override + public void close() throws Exception + { + IO.close(inputStream); + IO.close(outputStream); + } + + @Override + public ServletInputStream getInputStream() + { + return inputStream; + } + + @Override + public ServletOutputStream getOutputStream() + { + return outputStream; + } + }; + + upgradeHandler.init(webConnection); + return upgradeHandler; } @Override @@ -1382,6 +1631,11 @@ public AsyncContext startAsync() throws IllegalStateException { if (!isAsyncSupported()) throw new IllegalStateException("Async Not Supported"); + return forceStartAsync(); + } + + private AsyncContext forceStartAsync() + { ServletChannelState state = getServletRequestInfo().getState(); if (_async == null) _async = new AsyncContextState(state); diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java new file mode 100644 index 000000000000..90a95a9b1842 --- /dev/null +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java @@ -0,0 +1,131 @@ +package org.eclipse.jetty.ee11.servlet.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; + +public class ServletInputStreamWrapper extends ServletInputStream +{ + private final ServletInputStream _servletInputStream; + + public ServletInputStreamWrapper(ServletInputStream servletInputStream) + { + _servletInputStream = servletInputStream; + } + + @Override + public int readLine(byte[] b, int off, int len) throws IOException + { + return _servletInputStream.readLine(b, off, len); + } + + @Override + public boolean isFinished() + { + return _servletInputStream.isFinished(); + } + + @Override + public boolean isReady() + { + return _servletInputStream.isReady(); + } + + @Override + public void setReadListener(ReadListener readListener) + { + _servletInputStream.setReadListener(readListener); + } + + public static InputStream nullInputStream() + { + return InputStream.nullInputStream(); + } + + @Override + public int read() throws IOException + { + return _servletInputStream.read(); + } + + @Override + public int read(byte[] b) throws IOException + { + return _servletInputStream.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + return _servletInputStream.read(b, off, len); + } + + @Override + public byte[] readAllBytes() throws IOException + { + return _servletInputStream.readAllBytes(); + } + + @Override + public byte[] readNBytes(int len) throws IOException + { + return _servletInputStream.readNBytes(len); + } + + @Override + public int readNBytes(byte[] b, int off, int len) throws IOException + { + return _servletInputStream.readNBytes(b, off, len); + } + + @Override + public long skip(long n) throws IOException + { + return _servletInputStream.skip(n); + } + + @Override + public void skipNBytes(long n) throws IOException + { + _servletInputStream.skipNBytes(n); + } + + @Override + public int available() throws IOException + { + return _servletInputStream.available(); + } + + @Override + public void close() throws IOException + { + _servletInputStream.close(); + } + + @Override + public void mark(int readlimit) + { + _servletInputStream.mark(readlimit); + } + + @Override + public void reset() throws IOException + { + _servletInputStream.reset(); + } + + @Override + public boolean markSupported() + { + return _servletInputStream.markSupported(); + } + + @Override + public long transferTo(OutputStream out) throws IOException + { + return _servletInputStream.transferTo(out); + } +} diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletUpgradeTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletUpgradeTest.java index d08785673c45..3fb9eee21c9e 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletUpgradeTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ServletUpgradeTest.java @@ -17,6 +17,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletException; @@ -29,16 +32,18 @@ import jakarta.servlet.http.WebConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.Utf8StringBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.eclipse.jetty.util.StringUtil.CRLF; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertTrue; public class ServletUpgradeTest @@ -47,10 +52,13 @@ public class ServletUpgradeTest private Server server; private int port; + private static CountDownLatch destroyLatch; @BeforeEach public void setUp() throws Exception { + destroyLatch = new CountDownLatch(1); + server = new Server(); ServerConnector connector = new ServerConnector(server); @@ -72,130 +80,64 @@ public void tearDown() throws Exception server.stop(); } - @Disabled @Test public void upgradeTest() throws Exception { - boolean passed1 = false; - boolean passed2 = false; - boolean passed3 = false; - String expectedResponse1 = "TCKHttpUpgradeHandler.init"; - String expectedResponse2 = "onDataAvailable|Hello"; - String expectedResponse3 = "onDataAvailable|World"; - - InputStream input = null; - OutputStream output = null; - Socket s = null; - - try + Socket socket = new Socket("localhost", port); + socket.setSoTimeout(0); + InputStream input = socket.getInputStream(); + OutputStream output = socket.getOutputStream(); + + String request = "POST /TestServlet HTTP/1.1" + CRLF + + "Host: localhost:" + port + CRLF + + "Upgrade: YES" + CRLF + + "Connection: Upgrade" + CRLF + + CRLF; + + output.write(request.getBytes()); + writeChunk(output, "Hello"); + writeChunk(output, "World"); + output.flush(); + socket.shutdownOutput(); + + CompletableFuture futureContent = new CompletableFuture<>(); + new Thread(() -> { - s = new Socket("localhost", port); - output = s.getOutputStream(); - - StringBuilder reqStr = new StringBuilder() - .append("POST /TestServlet HTTP/1.1").append(CRLF) - .append("User-Agent: Java/1.6.0_33").append(CRLF) - .append("Host: localhost:").append(port).append(CRLF) - .append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2").append(CRLF) - .append("Upgrade: YES").append(CRLF) - .append("Connection: Upgrade").append(CRLF) - .append("Content-type: application/x-www-form-urlencoded").append(CRLF) - .append(CRLF); - - LOG.info("REQUEST=========" + reqStr.toString()); - output.write(reqStr.toString().getBytes()); - - LOG.info("Writing first chunk"); - writeChunk(output, "Hello"); - - LOG.info("Writing second chunk"); - writeChunk(output, "World"); - LOG.info("Consuming the response from the server"); - - // Consume the response from the server - input = s.getInputStream(); - int len; - byte[] b = new byte[1024]; - boolean receivedFirstMessage = false; - boolean receivedSecondMessage = false; - boolean receivedThirdMessage = false; - StringBuilder sb = new StringBuilder(); - while ((len = input.read(b)) != -1) - { - String line = new String(b, 0, len); - sb.append(line); - LOG.info("==============Read from server:" + CRLF + sb + CRLF); - if (passed1 = compareString(expectedResponse1, sb.toString())) - { - LOG.info("==============Received first expected response!" + CRLF); - receivedFirstMessage = true; - } - if (passed2 = compareString(expectedResponse2, sb.toString())) - { - LOG.info("==============Received second expected response!" + CRLF); - receivedSecondMessage = true; - } - if (passed3 = compareString(expectedResponse3, sb.toString())) - { - LOG.info("==============Received third expected response!" + CRLF); - receivedThirdMessage = true; - } - LOG.info("receivedFirstMessage : " + receivedFirstMessage); - LOG.info("receivedSecondMessage : " + receivedSecondMessage); - LOG.info("receivedThirdMessage : " + receivedThirdMessage); - if (receivedFirstMessage && receivedSecondMessage && receivedThirdMessage) - { - break; - } - } - } - finally - { + Utf8StringBuilder sb = new Utf8StringBuilder(); try { - if (input != null) + while (true) { - LOG.info("Closing input..."); - input.close(); - LOG.info("Input closed."); + int read = input.read(); + if (read == -1) + break; + sb.append((byte)read); } + futureContent.complete(sb.toCompleteString()); } - catch (Exception ex) + catch (Throwable t) { - LOG.error("Failed to close input:" + ex.getMessage(), ex); + LOG.warn("failed with content: " + sb, t); + futureContent.completeExceptionally(t); } - try - { - if (output != null) - { - LOG.info("Closing output..."); - output.close(); - LOG.info("Output closed ."); - } - } - catch (Exception ex) - { - LOG.error("Failed to close output:" + ex.getMessage(), ex); - } - - try - { - if (s != null) - { - LOG.info("Closing socket..." + CRLF); - s.close(); - LOG.info("Socked closed."); - } - } - catch (Exception ex) - { - LOG.error("Failed to close socket:" + ex.getMessage(), ex); - } - } - - assertTrue(passed1 && passed2 && passed3); + }).start(); + + String content = futureContent.get(5, TimeUnit.SECONDS); + String expectedContent = """ + TCKHttpUpgradeHandler.init\r + =onDataAvailable\r + HelloWorld\r + =onAllDataRead\r + """; + assertThat(content, startsWith("HTTP/1.1 101 Switching Protocols")); + assertThat(content, endsWith(expectedContent)); + + input.close(); + output.close(); + socket.close(); + assertTrue(destroyLatch.await(5, TimeUnit.SECONDS)); } private static class TestServlet extends HttpServlet @@ -227,7 +169,7 @@ public TestHttpUpgradeHandler() @Override public void destroy() { - LOG.debug("===============destroy"); + destroyLatch.countDown(); } @Override @@ -237,9 +179,9 @@ public void init(WebConnection wc) { ServletInputStream input = wc.getInputStream(); ServletOutputStream output = wc.getOutputStream(); - TestReadListener readListener = new TestReadListener("/", input, output); + TestReadListener readListener = new TestReadListener(input, output); input.setReadListener(readListener); - output.println("===============TCKHttpUpgradeHandler.init"); + output.println("TCKHttpUpgradeHandler.init"); output.flush(); } catch (Exception ex) @@ -253,20 +195,20 @@ private static class TestReadListener implements ReadListener { private final ServletInputStream input; private final ServletOutputStream output; - private final String delimiter; + private boolean outputOnDataAvailable = false; - TestReadListener(String del, ServletInputStream in, ServletOutputStream out) + TestReadListener(ServletInputStream in, ServletOutputStream out) { input = in; output = out; - delimiter = del; } + @Override public void onAllDataRead() { try { - output.println("=onAllDataRead"); + output.println("\r\n=onAllDataRead"); output.close(); } catch (Exception ex) @@ -275,11 +217,17 @@ public void onAllDataRead() } } + @Override public void onDataAvailable() { try { - output.println("=onDataAvailable"); + if (!outputOnDataAvailable) + { + outputOnDataAvailable = true; + output.println("=onDataAvailable"); + } + StringBuilder sb = new StringBuilder(); int len; byte[] b = new byte[1024]; @@ -288,7 +236,7 @@ public void onDataAvailable() String data = new String(b, 0, len); sb.append(data); } - output.println(delimiter + sb.toString()); + output.print(sb.toString()); output.flush(); } catch (Exception ex) @@ -297,50 +245,13 @@ public void onDataAvailable() } } + @Override public void onError(final Throwable t) { LOG.error("TestReadListener error", t); } } - private static boolean compareString(String expected, String actual) - { - String[] listExpected = expected.split("[|]"); - boolean found = true; - for (int i = 0, n = listExpected.length, startIdx = 0, bodyLength = actual.length(); i < n; i++) - { - String search = listExpected[i]; - if (startIdx >= bodyLength) - { - startIdx = bodyLength; - } - - int searchIdx = actual.toLowerCase().indexOf(search.toLowerCase(), startIdx); - - LOG.debug("[ServletTestUtil] Scanning response for " + "search string: '" + search + "' starting at index " + "location: " + startIdx); - if (searchIdx < 0) - { - found = false; - String s = "[ServletTestUtil] Unable to find the following " + - "search string in the server's " + - "response: '" + search + "' at index: " + - startIdx + - "\n[ServletTestUtil] Server's response:\n" + - "-------------------------------------------\n" + - actual + - "\n-------------------------------------------\n"; - LOG.debug(s); - break; - } - - LOG.debug("[ServletTestUtil] Found search string: '" + search + "' at index '" + searchIdx + "' in the server's " + "response"); - // the new searchIdx is the old index plus the lenght of the - // search string. - startIdx = searchIdx + search.length(); - } - return found; - } - private static void writeChunk(OutputStream out, String data) throws IOException { if (data != null) diff --git a/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java b/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java index 7904acaf364b..916adc57da39 100644 --- a/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java +++ b/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java @@ -44,10 +44,10 @@ import org.eclipse.jetty.ee11.servlet.ServletContextRequest; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; diff --git a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java index 25542d3dcf98..46248a3a8a37 100644 --- a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java +++ b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java @@ -41,11 +41,10 @@ import org.eclipse.jetty.ee9.servlet.ServletContextHandler; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.server.internal.HttpChannelState; -import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; From 0e73c563c81dc97a5c5c030e0255c98649ef2acb Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Thu, 22 Aug 2024 13:08:43 +1000 Subject: [PATCH 2/7] add missing licence header Signed-off-by: Lachlan Roberts --- .../servlet/util/ServletInputStreamWrapper.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java index 90a95a9b1842..0cdc6c3cab04 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java @@ -1,3 +1,16 @@ +// +// ======================================================================== +// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + package org.eclipse.jetty.ee11.servlet.util; import java.io.IOException; From cb691cd3ffa68488833b5e2f40759dc418a09a83 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Fri, 23 Aug 2024 14:07:05 +1000 Subject: [PATCH 3/7] PR #12186 - deprecate servletUpgrade method on HttpParser and rename to upgrade() Signed-off-by: Lachlan Roberts --- .../src/main/java/org/eclipse/jetty/http/HttpParser.java | 8 +++++++- .../org/eclipse/jetty/ee10/servlet/ServletApiRequest.java | 2 +- .../org/eclipse/jetty/ee11/servlet/ServletApiRequest.java | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 5198f28db74e..25f15c87ba89 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -2016,13 +2016,19 @@ public void reset() _headerComplete = false; } - public void servletUpgrade() + public void upgrade() { setState(State.EOF_CONTENT); _endOfContent = EndOfContent.EOF_CONTENT; _contentLength = -1; } + @Deprecated + public void servletUpgrade() + { + upgrade(); + } + protected void setState(State state) { if (debugEnabled) diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java index 63095e87b1c1..7d0acef79c6c 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java @@ -952,7 +952,7 @@ public void onError(Throwable t) } HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); - httpConnection.getParser().servletUpgrade(); + httpConnection.getParser().upgrade(); AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode outputStream.flush(); // commit the 101 response diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java index 0ad597cc3581..22168d2fe7c0 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java @@ -952,7 +952,7 @@ public void onError(Throwable t) } HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); - httpConnection.getParser().servletUpgrade(); + httpConnection.getParser().upgrade(); AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode outputStream.flush(); // commit the 101 response From b6f2c869e539a5ce296794f452a23df33d795917 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Thu, 29 Aug 2024 11:44:15 +1000 Subject: [PATCH 4/7] PR #12186 - Make HttpConnection internal and implement a public Upgrade interface Signed-off-by: Lachlan Roberts --- .../eclipse/jetty/client/HttpClientTest.java | 2 +- .../org/eclipse/jetty/http/HttpGenerator.java | 8 ++++++- .../org/eclipse/jetty/http/HttpParser.java | 2 +- .../jetty/http2/tests/HTTP2CServerTest.java | 2 +- .../java/org/eclipse/jetty/io/Connection.java | 5 +++++ .../src/main/java/module-info.java | 1 + .../jetty/server/AbstractConnector.java | 1 + .../server/ForwardedRequestCustomizer.java | 1 + .../jetty/server/HttpConnectionFactory.java | 1 + .../server/{ => internal}/HttpConnection.java | 22 ++++++++++++++++--- .../jetty/server/DelayedServerTest.java | 1 + .../jetty/server/ExtendedServerTest.java | 1 + .../ForwardedRequestCustomizerTest.java | 1 + .../jetty/server/HttpConnectionTest.java | 1 + .../jetty/server/HttpServerTestBase.java | 1 + .../jetty/server/ResponseCompleteTest.java | 1 + .../org/eclipse/jetty/server/ServerTest.java | 1 + .../SlowClientWithPipelinedRequestTest.java | 1 + .../org/eclipse/jetty/server/StopTest.java | 1 + .../server/handler/DelayedHandlerTest.java | 4 ++-- .../ssl/SniSslConnectionFactoryTest.java | 4 ++-- .../server/ssl/SslConnectionFactoryTest.java | 4 ++-- .../client/transport/ConnectionPoolTest.java | 2 +- .../jetty/ee10/servlet/ServletApiRequest.java | 19 ++++++++++------ .../ee10/test/GzipWithSendErrorTest.java | 2 +- .../jetty/ee11/servlet/ServletApiRequest.java | 20 +++++++++++------ .../ee11/test/GzipWithSendErrorTest.java | 2 +- .../org/eclipse/jetty/ee9/nested/Request.java | 2 +- .../jetty/ee9/test/GzipWithSendErrorTest.java | 2 +- 29 files changed, 83 insertions(+), 32 deletions(-) rename jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/{ => internal}/HttpConnection.java (98%) diff --git a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index 7d229d1d0315..f76edcfd7e4b 100644 --- a/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-core/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -1865,7 +1865,7 @@ public void onError(Throwable t) } }); // Close the parser to cause the issue. - org.eclipse.jetty.server.HttpConnection.getCurrentConnection().getParser().close(); + org.eclipse.jetty.server.internal.HttpConnection.getCurrentConnection().getParser().close(); } }); server.start(); diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java index 595fb5f5df5e..939c418ccf97 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java @@ -455,12 +455,18 @@ else if (status == HttpStatus.NO_CONTENT_204 || status == HttpStatus.NOT_MODIFIE } } - public void servletUpgrade() + public void upgrade() { _noContentResponse = false; _state = State.COMMITTED; } + @Deprecated(since = "12.1.0", forRemoval = true) + public void servletUpgrade() + { + upgrade(); + } + private void prepareChunk(ByteBuffer chunk, int remaining) { // if we need CRLF add this to header diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 25f15c87ba89..5f91d39e5bd9 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -2023,7 +2023,7 @@ public void upgrade() _contentLength = -1; } - @Deprecated + @Deprecated(since = "12.1.0", forRemoval = true) public void servletUpgrade() { upgrade(); diff --git a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java index 3d61be8aa01e..13617566c882 100644 --- a/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java +++ b/jetty-core/jetty-http2/jetty-http2-tests/src/test/java/org/eclipse/jetty/http2/tests/HTTP2CServerTest.java @@ -42,9 +42,9 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.Utf8StringBuilder; diff --git a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java index edbd16f20580..fff714bdc480 100644 --- a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java +++ b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java @@ -140,6 +140,11 @@ interface UpgradeTo void onUpgradeTo(ByteBuffer buffer); } + interface Upgrade + { + void upgrade(); + } + /** *

A Listener for connection events.

*

Listeners can be added to a {@link Connection} to get open and close events. diff --git a/jetty-core/jetty-server/src/main/java/module-info.java b/jetty-core/jetty-server/src/main/java/module-info.java index 8f3ef3e0f50a..949eca15a8f1 100644 --- a/jetty-core/jetty-server/src/main/java/module-info.java +++ b/jetty-core/jetty-server/src/main/java/module-info.java @@ -28,4 +28,5 @@ exports org.eclipse.jetty.server.jmx to org.eclipse.jetty.jmx; + exports org.eclipse.jetty.server.internal; } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index 72391323943f..5be4f03d2a35 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -37,6 +37,7 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.io.ssl.SslConnection; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.ProcessorUtils; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index 3237c6486732..eddb9f7cfcff 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.QuotedCSVParser; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.Index; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java index 502131b53b98..30b5d9b5067a 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnectionFactory.java @@ -19,6 +19,7 @@ import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.annotation.Name; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java similarity index 98% rename from jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java rename to jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java index 4a32932a5e1c..50b6afb9397a 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java @@ -11,7 +11,7 @@ // ======================================================================== // -package org.eclipse.jetty.server; +package org.eclipse.jetty.server.internal; import java.io.IOException; import java.nio.ByteBuffer; @@ -53,7 +53,16 @@ import org.eclipse.jetty.io.RetainableByteBuffer; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.ssl.SslConnection; -import org.eclipse.jetty.server.internal.HttpChannelState; +import org.eclipse.jetty.server.AbstractMetaDataConnection; +import org.eclipse.jetty.server.ConnectionFactory; +import org.eclipse.jetty.server.ConnectionMetaData; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpChannel; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpStream; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.TunnelSupport; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.HostPort; @@ -71,7 +80,7 @@ /** *

A {@link Connection} that handles the HTTP protocol.

*/ -public class HttpConnection extends AbstractMetaDataConnection implements Runnable, Connection.UpgradeFrom, Connection.UpgradeTo, ConnectionMetaData +public class HttpConnection extends AbstractMetaDataConnection implements Runnable, Connection.UpgradeFrom, Connection.UpgradeTo, Connection.Upgrade, ConnectionMetaData { private static final Logger LOG = LoggerFactory.getLogger(HttpConnection.class); private static final HttpField PREAMBLE_UPGRADE_H2C = new HttpField(HttpHeader.UPGRADE, "h2c"); @@ -326,6 +335,13 @@ public void onUpgradeTo(ByteBuffer buffer) BufferUtil.append(getRequestBuffer(), buffer); } + @Override + public void upgrade() + { + getParser().upgrade(); + getGenerator().upgrade(); + } + void releaseRequestBuffer() { if (_retainableByteBuffer != null && _retainableByteBuffer.isEmpty()) diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java index d20abd8cb279..3a1ec920d762 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/DelayedServerTest.java @@ -19,6 +19,7 @@ import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.BeforeEach; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java index 67ac2eaae950..7d9aa6812f80 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ExtendedServerTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.io.ManagedSelector; import org.eclipse.jetty.io.SocketChannelEndPoint; import org.eclipse.jetty.server.internal.HttpChannelState; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.NanoTime; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java index ae588464a39c..2b8b97036a4d 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java @@ -26,6 +26,7 @@ import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index fc078af5030d..b93a6daa100f 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -46,6 +46,7 @@ import org.eclipse.jetty.io.Content; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.handler.DumpHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.NanoTime; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index 77c18c6f3bd4..8f1c60271b1a 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -48,6 +48,7 @@ import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.handler.EchoHandler; import org.eclipse.jetty.server.handler.HelloHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java index 4a9619cd358c..482cfe2a1e5c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseCompleteTest.java @@ -26,6 +26,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.logging.StacklessLogging; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.component.LifeCycle; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java index dccc272d24dc..dcca3eb0375a 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ServerTest.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.internal.HttpChannelState; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Blocker; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Jetty; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java index 959272f227b5..12069ad7e157 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java @@ -23,6 +23,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.Callback; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java index f044a2d62339..48bcf7e9a61b 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/StopTest.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.FutureCallback; diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java index 4b0daad89863..88c213a3132d 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/DelayedHandlerTest.java @@ -298,7 +298,7 @@ public boolean handle(Request request, Response response, Callback callback) thr ByteArrayOutputStream out = new ByteArrayOutputStream(8192); new Throwable().printStackTrace(new PrintStream(out)); String stack = out.toString(StandardCharsets.ISO_8859_1); - assertThat(stack, containsString("org.eclipse.jetty.server.HttpConnection.onFillable")); + assertThat(stack, containsString("org.eclipse.jetty.server.internal.HttpConnection.onFillable")); assertThat(stack, containsString("org.eclipse.jetty.server.handler.DelayedHandler.handle")); // Check the content is available @@ -469,7 +469,7 @@ public boolean handle(Request request, Response response, Callback callback) thr ByteArrayOutputStream out = new ByteArrayOutputStream(8192); new Throwable().printStackTrace(new PrintStream(out)); String stack = out.toString(StandardCharsets.ISO_8859_1); - assertThat(stack, containsString("org.eclipse.jetty.server.HttpConnection.onFillable")); + assertThat(stack, containsString("org.eclipse.jetty.server.internal.HttpConnection.onFillable")); assertThat(stack, containsString("org.eclipse.jetty.server.handler.DelayedHandler.handle")); Fields fields = FormFields.from(request).get(1, TimeUnit.NANOSECONDS); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java index d833123926b3..46784e2434ec 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java @@ -494,8 +494,8 @@ protected void customize(Socket socket, Class connection, assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); - assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true", history.poll()); - assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true", history.poll()); + assertEquals("customize connector class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); + assertEquals("customize http class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); assertEquals(0, history.size()); } diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java index 04f4aef7305c..ebe49e17e0e1 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java @@ -178,8 +178,8 @@ protected void customize(Socket socket, Class connection, assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false", history.poll()); - assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true", history.poll()); - assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true", history.poll()); + assertEquals("customize connector class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); + assertEquals("customize http class org.eclipse.jetty.server.internal.HttpConnection,true", history.poll()); assertEquals(0, history.size()); } diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java index 1f2c4ee6092b..a634883faea3 100644 --- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java +++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/ConnectionPoolTest.java @@ -24,7 +24,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.quic.server.ServerQuicConnection; -import org.eclipse.jetty.server.HttpConnection; +import org.eclipse.jetty.server.internal.HttpConnection; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java index 7d0acef79c6c..b07044e071fd 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java @@ -78,6 +78,7 @@ import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.SetCookieParser; import org.eclipse.jetty.http.pathmap.MatchedResource; +import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.security.AuthenticationState; @@ -85,7 +86,6 @@ import org.eclipse.jetty.server.ConnectionMetaData; import org.eclipse.jetty.server.CookieCache; import org.eclipse.jetty.server.FormFields; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -951,13 +951,18 @@ public void onError(Throwable t) throw new ServletException("Unable to instantiate handler class", e); } - HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); - httpConnection.getParser().upgrade(); + Connection connection = _servletContextRequest.getConnectionMetaData().getConnection(); + if (connection instanceof Connection.Upgrade upgradeableConnection) + { + outputStream.flush(); // commit the 101 response + upgradeableConnection.upgrade(); + } + else + { + LOG.warn("Unexpected connection type {}", connection); + throw new IllegalStateException(); + } AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode - - outputStream.flush(); // commit the 101 response - httpConnection.getGenerator().servletUpgrade(); // tell the generator it can send data as-is - CompletableFuture.allOf(inputStreamComplete, outputStreamComplete).whenComplete((result, failure) -> { upgradeHandler.destroy(); diff --git a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java index 63d851f604d9..67c5bfb08e47 100644 --- a/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java +++ b/jetty-ee10/jetty-ee10-tests/jetty-ee10-test-integration/src/test/java/org/eclipse/jetty/ee10/test/GzipWithSendErrorTest.java @@ -44,10 +44,10 @@ import org.eclipse.jetty.ee10.servlet.ServletContextRequest; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java index 22168d2fe7c0..935d20c6e029 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java @@ -78,6 +78,7 @@ import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.SetCookieParser; import org.eclipse.jetty.http.pathmap.MatchedResource; +import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.security.AuthenticationState; @@ -85,7 +86,6 @@ import org.eclipse.jetty.server.ConnectionMetaData; import org.eclipse.jetty.server.CookieCache; import org.eclipse.jetty.server.FormFields; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpCookieUtils; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -951,13 +951,19 @@ public void onError(Throwable t) throw new ServletException("Unable to instantiate handler class", e); } - HttpConnection httpConnection = (HttpConnection)_servletContextRequest.getConnectionMetaData().getConnection(); - httpConnection.getParser().upgrade(); - AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode - - outputStream.flush(); // commit the 101 response - httpConnection.getGenerator().servletUpgrade(); // tell the generator it can send data as-is + Connection connection = _servletContextRequest.getConnectionMetaData().getConnection(); + if (connection instanceof Connection.Upgrade upgradeableConnection) + { + outputStream.flush(); // commit the 101 response + upgradeableConnection.upgrade(); + } + else + { + LOG.warn("Unexpected connection type {}", connection); + throw new IllegalStateException(); + } + AsyncContext asyncContext = forceStartAsync(); // force the servlet in async mode CompletableFuture.allOf(inputStreamComplete, outputStreamComplete).whenComplete((result, failure) -> { upgradeHandler.destroy(); diff --git a/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java b/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java index 916adc57da39..7904acaf364b 100644 --- a/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java +++ b/jetty-ee11/jetty-ee11-tests/jetty-ee11-test-integration/src/test/java/org/eclipse/jetty/ee11/test/GzipWithSendErrorTest.java @@ -44,10 +44,10 @@ import org.eclipse.jetty.ee11.servlet.ServletContextRequest; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java index cd87e9962795..43e62a3ead0c 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java @@ -596,7 +596,7 @@ public ComplianceViolation.Listener getComplianceViolationListener() *
*
org.eclipse.jetty.server.Server
The Jetty Server instance
*
org.eclipse.jetty.server.HttpChannel
The HttpChannel for this request
- *
org.eclipse.jetty.server.HttpConnection
The HttpConnection or null if another transport is used
+ *
org.eclipse.jetty.server.internal.HttpConnection
The HttpConnection or null if another transport is used
*
* While these attributes may look like security problems, they are exposing nothing that is not already * available via reflection from a Request instance. diff --git a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java index 46248a3a8a37..a640c74429f7 100644 --- a/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java +++ b/jetty-ee9/jetty-ee9-tests/jetty-ee9-test-integration/src/test/java/org/eclipse/jetty/ee9/test/GzipWithSendErrorTest.java @@ -41,10 +41,10 @@ import org.eclipse.jetty.ee9.servlet.ServletContextHandler; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.handler.gzip.GzipHandler; +import org.eclipse.jetty.server.internal.HttpConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; From e13b9ad84c00b1ed9e61108c2dfbe64c295dbc1b Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Thu, 29 Aug 2024 12:16:33 +1000 Subject: [PATCH 5/7] PR #12186 - changes from review Signed-off-by: Lachlan Roberts --- .../src/main/java/module-info.java | 1 - .../util/ServletInputStreamWrapper.java | 30 ------ .../util/ServletOutputStreamWrapper.java | 96 ------------------- 3 files changed, 127 deletions(-) diff --git a/jetty-core/jetty-server/src/main/java/module-info.java b/jetty-core/jetty-server/src/main/java/module-info.java index 949eca15a8f1..8f3ef3e0f50a 100644 --- a/jetty-core/jetty-server/src/main/java/module-info.java +++ b/jetty-core/jetty-server/src/main/java/module-info.java @@ -28,5 +28,4 @@ exports org.eclipse.jetty.server.jmx to org.eclipse.jetty.jmx; - exports org.eclipse.jetty.server.internal; } diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java index 0cdc6c3cab04..91de243b87e1 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletInputStreamWrapper.java @@ -14,7 +14,6 @@ package org.eclipse.jetty.ee11.servlet.util; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import jakarta.servlet.ReadListener; @@ -29,12 +28,6 @@ public ServletInputStreamWrapper(ServletInputStream servletInputStream) _servletInputStream = servletInputStream; } - @Override - public int readLine(byte[] b, int off, int len) throws IOException - { - return _servletInputStream.readLine(b, off, len); - } - @Override public boolean isFinished() { @@ -53,11 +46,6 @@ public void setReadListener(ReadListener readListener) _servletInputStream.setReadListener(readListener); } - public static InputStream nullInputStream() - { - return InputStream.nullInputStream(); - } - @Override public int read() throws IOException { @@ -76,24 +64,6 @@ public int read(byte[] b, int off, int len) throws IOException return _servletInputStream.read(b, off, len); } - @Override - public byte[] readAllBytes() throws IOException - { - return _servletInputStream.readAllBytes(); - } - - @Override - public byte[] readNBytes(int len) throws IOException - { - return _servletInputStream.readNBytes(len); - } - - @Override - public int readNBytes(byte[] b, int off, int len) throws IOException - { - return _servletInputStream.readNBytes(b, off, len); - } - @Override public long skip(long n) throws IOException { diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletOutputStreamWrapper.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletOutputStreamWrapper.java index 773925651676..97c808ab04c7 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletOutputStreamWrapper.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/util/ServletOutputStreamWrapper.java @@ -14,7 +14,6 @@ package org.eclipse.jetty.ee11.servlet.util; import java.io.IOException; -import java.io.OutputStream; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; @@ -28,96 +27,6 @@ public ServletOutputStreamWrapper(ServletOutputStream outputStream) _outputStream = outputStream; } - @Override - public void print(String s) throws IOException - { - _outputStream.print(s); - } - - @Override - public void print(boolean b) throws IOException - { - _outputStream.print(b); - } - - @Override - public void print(char c) throws IOException - { - _outputStream.print(c); - } - - @Override - public void print(int i) throws IOException - { - _outputStream.print(i); - } - - @Override - public void print(long l) throws IOException - { - _outputStream.print(l); - } - - @Override - public void print(float f) throws IOException - { - _outputStream.print(f); - } - - @Override - public void print(double d) throws IOException - { - _outputStream.print(d); - } - - @Override - public void println() throws IOException - { - _outputStream.println(); - } - - @Override - public void println(String s) throws IOException - { - _outputStream.println(s); - } - - @Override - public void println(boolean b) throws IOException - { - _outputStream.println(b); - } - - @Override - public void println(char c) throws IOException - { - _outputStream.println(c); - } - - @Override - public void println(int i) throws IOException - { - _outputStream.println(i); - } - - @Override - public void println(long l) throws IOException - { - _outputStream.println(l); - } - - @Override - public void println(float f) throws IOException - { - _outputStream.println(f); - } - - @Override - public void println(double d) throws IOException - { - _outputStream.println(d); - } - @Override public boolean isReady() { @@ -130,11 +39,6 @@ public void setWriteListener(WriteListener writeListener) _outputStream.setWriteListener(writeListener); } - public static OutputStream nullOutputStream() - { - return OutputStream.nullOutputStream(); - } - @Override public void write(int b) throws IOException { From c64e0bbbe60bed35f68664d49f8a8e7eea9d1a2a Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Thu, 29 Aug 2024 12:31:37 +1000 Subject: [PATCH 6/7] PR #12186 - add javadoc for Connection.Upgrade Signed-off-by: Lachlan Roberts --- .../src/main/java/org/eclipse/jetty/io/Connection.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java index fff714bdc480..be93c742fb5e 100644 --- a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java +++ b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java @@ -140,6 +140,13 @@ interface UpgradeTo void onUpgradeTo(ByteBuffer buffer); } + /** + *

{@link Connection} implementations implement this interface when they + * can be upgraded to a different protocol. For an HTTP request it will read + * content from the request until EOF treating this as bytes over the new + * protocol.

+ *

This is used for the {@code HttpServletRequest#upgrade()} implementation.

+ */ interface Upgrade { void upgrade(); From f795fb10d086b527d0320f2b23b3ff61382be3d9 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Mon, 2 Sep 2024 15:52:53 +1000 Subject: [PATCH 7/7] PR # 12186 - changes from review Signed-off-by: Lachlan Roberts --- .../java/org/eclipse/jetty/http/HttpGenerator.java | 4 ++-- .../main/java/org/eclipse/jetty/http/HttpParser.java | 4 ++-- .../main/java/org/eclipse/jetty/io/Connection.java | 12 +++++------- .../jetty/server/internal/HttpConnection.java | 8 ++++---- .../jetty/ee10/servlet/ServletApiRequest.java | 4 ++-- .../jetty/ee11/servlet/ServletApiRequest.java | 4 ++-- .../java/org/eclipse/jetty/ee9/nested/Request.java | 2 +- 7 files changed, 18 insertions(+), 20 deletions(-) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java index 939c418ccf97..c620216a8298 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java @@ -455,7 +455,7 @@ else if (status == HttpStatus.NO_CONTENT_204 || status == HttpStatus.NOT_MODIFIE } } - public void upgrade() + public void startTunnel() { _noContentResponse = false; _state = State.COMMITTED; @@ -464,7 +464,7 @@ public void upgrade() @Deprecated(since = "12.1.0", forRemoval = true) public void servletUpgrade() { - upgrade(); + startTunnel(); } private void prepareChunk(ByteBuffer chunk, int remaining) diff --git a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 5f91d39e5bd9..de5f6edc3d36 100644 --- a/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-core/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -2016,7 +2016,7 @@ public void reset() _headerComplete = false; } - public void upgrade() + public void startTunnel() { setState(State.EOF_CONTENT); _endOfContent = EndOfContent.EOF_CONTENT; @@ -2026,7 +2026,7 @@ public void upgrade() @Deprecated(since = "12.1.0", forRemoval = true) public void servletUpgrade() { - upgrade(); + startTunnel(); } protected void setState(State state) diff --git a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java index be93c742fb5e..edf6d0b5a3bf 100644 --- a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java +++ b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java @@ -141,15 +141,13 @@ interface UpgradeTo } /** - *

{@link Connection} implementations implement this interface when they - * can be upgraded to a different protocol. For an HTTP request it will read - * content from the request until EOF treating this as bytes over the new - * protocol.

- *

This is used for the {@code HttpServletRequest#upgrade()} implementation.

+ *

Start a tunnel over the current connection without replacing the connection.

+ *

This can be used for upgrade within a connection, but it is not really an upgrade for this connection + * as the connection remains and just tunnels data to/from its endpoint.

*/ - interface Upgrade + interface Tunnel { - void upgrade(); + void startTunnel(); } /** diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java index 50b6afb9397a..327a3e62c48d 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/internal/HttpConnection.java @@ -80,7 +80,7 @@ /** *

A {@link Connection} that handles the HTTP protocol.

*/ -public class HttpConnection extends AbstractMetaDataConnection implements Runnable, Connection.UpgradeFrom, Connection.UpgradeTo, Connection.Upgrade, ConnectionMetaData +public class HttpConnection extends AbstractMetaDataConnection implements Runnable, Connection.UpgradeFrom, Connection.UpgradeTo, Connection.Tunnel, ConnectionMetaData { private static final Logger LOG = LoggerFactory.getLogger(HttpConnection.class); private static final HttpField PREAMBLE_UPGRADE_H2C = new HttpField(HttpHeader.UPGRADE, "h2c"); @@ -336,10 +336,10 @@ public void onUpgradeTo(ByteBuffer buffer) } @Override - public void upgrade() + public void startTunnel() { - getParser().upgrade(); - getGenerator().upgrade(); + getParser().startTunnel(); + getGenerator().startTunnel(); } void releaseRequestBuffer() diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java index b07044e071fd..cd5504e9c120 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletApiRequest.java @@ -952,10 +952,10 @@ public void onError(Throwable t) } Connection connection = _servletContextRequest.getConnectionMetaData().getConnection(); - if (connection instanceof Connection.Upgrade upgradeableConnection) + if (connection instanceof Connection.Tunnel upgradeableConnection) { outputStream.flush(); // commit the 101 response - upgradeableConnection.upgrade(); + upgradeableConnection.startTunnel(); } else { diff --git a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java index 935d20c6e029..5a7203b31009 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletApiRequest.java @@ -952,10 +952,10 @@ public void onError(Throwable t) } Connection connection = _servletContextRequest.getConnectionMetaData().getConnection(); - if (connection instanceof Connection.Upgrade upgradeableConnection) + if (connection instanceof Connection.Tunnel upgradeableConnection) { outputStream.flush(); // commit the 101 response - upgradeableConnection.upgrade(); + upgradeableConnection.startTunnel(); } else { diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java index 43e62a3ead0c..ee810f9fe711 100644 --- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java +++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/Request.java @@ -596,7 +596,7 @@ public ComplianceViolation.Listener getComplianceViolationListener() *
*
org.eclipse.jetty.server.Server
The Jetty Server instance
*
org.eclipse.jetty.server.HttpChannel
The HttpChannel for this request
- *
org.eclipse.jetty.server.internal.HttpConnection
The HttpConnection or null if another transport is used
+ *
org.eclipse.jetty.io.Connection
The Connection or null if another transport is used
*
* While these attributes may look like security problems, they are exposing nothing that is not already * available via reflection from a Request instance.