diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java
index 6cc7aac6d4dc..8d193d50885e 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java
@@ -292,10 +292,10 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r
InputStreamResponseListener listener = new InputStreamResponseListener();
client.newRequest("localhost", connector.getLocalPort())
.scheme(scenario.getScheme())
- .timeout(5, TimeUnit.SECONDS)
+ .timeout(20, TimeUnit.SECONDS)
.send(listener);
- Response response = listener.get(5, TimeUnit.SECONDS);
+ Response response = listener.get(20, TimeUnit.SECONDS);
assertEquals(HttpStatus.OK_200, response.getStatus());
ByteArrayOutputStream output = new ByteArrayOutputStream();
diff --git a/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/HttpChannelOverHTTP3.java b/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/HttpChannelOverHTTP3.java
index f8759b7fd452..cad2ff628379 100644
--- a/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/HttpChannelOverHTTP3.java
+++ b/jetty-http3/http3-server/src/main/java/org/eclipse/jetty/http3/server/internal/HttpChannelOverHTTP3.java
@@ -161,13 +161,11 @@ public Runnable onRequest(HeadersFrame frame)
{
if (LOG.isDebugEnabled())
LOG.debug("onRequest() failure", x);
- onBadMessage(x);
- return null;
+ return () -> onBadMessage(x);
}
catch (Throwable x)
{
- onBadMessage(new BadMessageException(HttpStatus.INTERNAL_SERVER_ERROR_500, null, x));
- return null;
+ return () -> onBadMessage(new BadMessageException(HttpStatus.INTERNAL_SERVER_ERROR_500, null, x));
}
}
diff --git a/jetty-p2/pom.xml b/jetty-p2/pom.xml
index 2361427106d0..f8bd0a333712 100644
--- a/jetty-p2/pom.xml
+++ b/jetty-p2/pom.xml
@@ -43,7 +43,7 @@
artifacts are created -->
org.eclipse.jetty
- jetty-bom
+ jetty-home
${project.version}
pom
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
index 65becfe88bd6..e5ccd17d100d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java
@@ -664,6 +664,12 @@ public void setInflateBufferSize(int size)
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
+ if (baseRequest.isHandled())
+ {
+ super.handle(target, baseRequest, request, response);
+ return;
+ }
+
final ServletContext context = baseRequest.getServletContext();
final String path = baseRequest.getPathInContext();
LOG.debug("{} handle {} in {}", this, baseRequest, context);
@@ -671,7 +677,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
if (!_dispatchers.contains(baseRequest.getDispatcherType()))
{
LOG.debug("{} excluded by dispatcherType {}", this, baseRequest.getDispatcherType());
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
return;
}
@@ -688,6 +694,15 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
baseRequest.getHttpInput().addInterceptor(gzipHttpInputInterceptor);
}
+ // From here on out, the response output gzip determination is made
+
+ // Don't attempt to modify the response output if it's already committed.
+ if (response.isCommitted())
+ {
+ super.handle(target, baseRequest, request, response);
+ return;
+ }
+
// Are we already being gzipped?
HttpOutput out = baseRequest.getResponse().getHttpOutput();
HttpOutput.Interceptor interceptor = out.getInterceptor();
@@ -764,7 +779,7 @@ else if (COMMA_GZIP.matcher(field.getValue()).matches())
if (alreadyGzipped)
{
LOG.debug("{} already intercepting {}", this, request);
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
return;
}
@@ -772,7 +787,7 @@ else if (COMMA_GZIP.matcher(field.getValue()).matches())
if (!_methods.test(baseRequest.getMethod()))
{
LOG.debug("{} excluded by method {}", this, request);
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
return;
}
@@ -781,7 +796,7 @@ else if (COMMA_GZIP.matcher(field.getValue()).matches())
if (!isPathGzipable(path))
{
LOG.debug("{} excluded by path {}", this, request);
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
return;
}
@@ -794,7 +809,7 @@ else if (COMMA_GZIP.matcher(field.getValue()).matches())
{
LOG.debug("{} excluded by path suffix mime type {}", this, request);
// handle normally without setting vary header
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
return;
}
}
@@ -804,9 +819,7 @@ else if (COMMA_GZIP.matcher(field.getValue()).matches())
{
// install interceptor and handle
out.setInterceptor(new GzipHttpOutputInterceptor(this, getVaryField(), baseRequest.getHttpChannel(), origInterceptor, isSyncFlush()));
-
- if (_handler != null)
- _handler.handle(target, baseRequest, request, response);
+ super.handle(target, baseRequest, request, response);
}
finally
{
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerIsHandledTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerIsHandledTest.java
new file mode 100644
index 000000000000..8bef4367c23f
--- /dev/null
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerIsHandledTest.java
@@ -0,0 +1,124 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2022 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.servlet;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingQueue;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.server.handler.gzip.GzipHandler;
+import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.util.resource.PathResource;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Tests of behavior of GzipHandler when Request.isHandled() or Response.isCommitted() is true
+ */
+public class GzipHandlerIsHandledTest
+{
+ public WorkDir workDir;
+
+ private Server server;
+ private HttpClient client;
+ public LinkedBlockingQueue events = new LinkedBlockingQueue<>();
+
+ public void startServer(Handler rootHandler) throws Exception
+ {
+ server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ server.setHandler(rootHandler);
+ server.start();
+
+ client = new HttpClient();
+ client.start();
+ }
+
+ @AfterEach
+ public void tearDown()
+ {
+ LifeCycle.stop(client);
+ LifeCycle.stop(server);
+ }
+
+ @Test
+ public void testRequest() throws Exception
+ {
+ HandlerCollection handlers = new HandlerCollection();
+
+ ResourceHandler resourceHandler = new ResourceHandler();
+ resourceHandler.setBaseResource(new PathResource(workDir.getPath()));
+ resourceHandler.setDirectoriesListed(true);
+ resourceHandler.setHandler(new EventHandler(events, "ResourceHandler"));
+
+ GzipHandler gzipHandler = new GzipHandler();
+ gzipHandler.setMinGzipSize(32);
+ gzipHandler.setHandler(new EventHandler(events, "GzipHandler-wrapped-handler"));
+
+ handlers.setHandlers(new Handler[]{resourceHandler, gzipHandler, new DefaultHandler()});
+
+ startServer(handlers);
+
+ ContentResponse response = client.GET(server.getURI().resolve("/"));
+ assertThat("response.status", response.getStatus(), is(200));
+ // we should have received a directory listing from the ResourceHandler
+ assertThat("response.content", response.getContentAsString(), containsString("Directory: /"));
+ // resource handler should have handled the request
+ // the gzip handler and default handlers should have been executed, seeing as this is a HandlerCollection
+ // but the gzip handler should not have acted on the request, as the response is committed
+ assertThat("One event should have been recorded", events.size(), is(1));
+ // the event handler should see the request.isHandled = true
+ // and response.isCommitted = true as the gzip handler didn't really do anything due to these
+ // states and let the wrapped handler (the EventHandler in this case) make the call on what it should do.
+ assertThat("Event indicating that GzipHandler-wrapped-handler ran", events.remove(), is("GzipHandler-wrapped-handler [request.isHandled=true, response.isCommitted=true]"));
+ }
+
+ private static class EventHandler extends AbstractHandler
+ {
+ private final LinkedBlockingQueue events;
+ private final String action;
+
+ public EventHandler(LinkedBlockingQueue events, String action)
+ {
+ this.events = events;
+ this.action = action;
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ events.offer(String.format("%s [request.isHandled=%b, response.isCommitted=%b]", action, baseRequest.isHandled(), response.isCommitted()));
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index a9617c03cc04..8164efabfcab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,7 +103,7 @@
5.8.2
2.0.2
2.17.2
- 1.3.0-alpha15
+ 1.3.0-alpha16
3.0.4
10.3.6
0.13.1
@@ -116,12 +116,12 @@
1.2.0
1.2.0
2.1.1
- 3.4.1
+ 3.4.2
2.0.0-alpha6
2.1.1.RELEASE
1.2.5
1.2.5
- 1.17.1
+ 1.17.2
3.1.9.Final
1.6.0.Final
1.19.0.Final
@@ -141,7 +141,7 @@
4.1
3.1.0
3.3.0
- 5.1.4
+ 5.1.6
3.2.0
3.1.2
3.10.1
@@ -166,8 +166,8 @@
3.0.0-M5
3.2.1
3.3.2
- 4.6.0.0
- 2.10.0
+ 4.7.0.0
+ 2.11.0
false