diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ResponseTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ResponseTest.java index 23f9577b94bf..5a17565fa146 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ResponseTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/ResponseTest.java @@ -18,6 +18,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.function.BiConsumer; import java.util.stream.Stream; import jakarta.servlet.ServletException; @@ -242,4 +243,100 @@ else if (!location.startsWith("http:/")) assertThat(actual, containsString(expected)); } } + + @Test + public void testSetContentLengthAfterCommit() throws Exception + { + testActionAfterCommit((request, response) -> + { + response.setContentLength(20); + assertThat(response.getHeader("Content-Length"), is("5")); + }); + } + + @Test + public void testSetHeaderAfterCommit() throws Exception + { + testActionAfterCommit((request, response) -> + { + response.setHeader("foo", "bar"); + assertThat(response.getHeader("foo"), nullValue()); + }); + } + + @Test + public void testAddHeaderAfterCommit() throws Exception + { + testActionAfterCommit((request, response) -> + { + response.addHeader("foo", "bar"); + assertThat(response.getHeader("foo"), nullValue()); + }); + } + + @Test + public void testAddDateHeaderAfterCommit() throws Exception + { + testActionAfterCommit((req, resp) -> + { + resp.addDateHeader("foo-date", System.currentTimeMillis()); + assertThat(resp.getHeader("foo-date"), nullValue()); + }); + } + + @Test + public void testSetDateHeaderAfterCommit() throws Exception + { + testActionAfterCommit((req, resp) -> + { + resp.setDateHeader("foo-date", System.currentTimeMillis()); + assertThat(resp.getHeader("foo-date"), nullValue()); + }); + } + + @Test + public void testSetStatusAfterCommit() throws Exception + { + testActionAfterCommit((req, resp) -> + { + resp.setStatus(HttpStatus.FORBIDDEN_403); + assertThat(resp.getStatus(), is(HttpStatus.OK_200)); + }); + } + + private void testActionAfterCommit(BiConsumer action) + throws Exception + { + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + HttpServlet servlet = new HttpServlet() + { + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + response.setContentType("text/plain; charset=US-ASCII"); + response.getWriter().println("Hello"); + response.getWriter().flush(); + assertThat(response.isCommitted(), is(Boolean.TRUE)); + action.accept(request, response); + } + }; + + contextHandler.addServlet(servlet, "/servlet/*"); + startServer(contextHandler); + + HttpTester.Request request = new HttpTester.Request(); + request.setMethod("GET"); + request.setURI("/servlet/"); + request.setVersion(HttpVersion.HTTP_1_1); + request.setHeader("Connection", "close"); + request.setHeader("Host", "test"); + + ByteBuffer responseBuffer = _connector.getResponse(request.generate()); + HttpTester.Response response = HttpTester.parseResponse(responseBuffer); + + assertThat(response.getStatus(), is(200)); + assertThat(response.get("Content-Type"), is("text/plain; charset=US-ASCII")); + assertThat(response.getContent(), containsString("Hello")); + } } diff --git a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/SetCookieTest.java b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/SetCookieTest.java index 73f3660f4e88..cddddc4d4014 100644 --- a/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/SetCookieTest.java +++ b/jetty-ee11/jetty-ee11-servlet/src/test/java/org/eclipse/jetty/ee11/servlet/SetCookieTest.java @@ -30,6 +30,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; public class SetCookieTest { @@ -85,4 +86,40 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se assertThat(response.getStatus(), is(200)); assertThat(response.get(HttpHeader.SET_COOKIE), is("key=foo; SameSite=Lax")); } + + @Test + public void testAddCookieAfterCommit() throws Exception + { + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + + HttpServlet testServlet = new HttpServlet() + { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + resp.setCharacterEncoding("utf-8"); + resp.setContentType("text/plain"); + resp.getWriter().printf("pathInfo: " + req.getPathInfo()); + resp.getWriter().flush(); + //Adding a cookie after the response is committed should be a no-op + Cookie cookie = new Cookie("key", "foo"); + + resp.addCookie(cookie); + assertThat(resp.getHeader("Set-Cookie"), nullValue()); + } + }; + + contextHandler.addServlet(testServlet, "/test/*"); + startServer(contextHandler); + String rawRequest = """ + GET /test/after-commit HTTP/1.1 + Host: test + Connection: close + + """; + HttpTester.Response response = HttpTester.parseResponse(connector.getResponse(rawRequest)); + assertThat(response.getStatus(), is(200)); + assertThat(response.get(HttpHeader.SET_COOKIE), nullValue()); + } }