This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new dcb4e3f347 Add support for server and serverRemoveAppProvidedValues to h2 dcb4e3f347 is described below commit dcb4e3f347844d39ce59fd4793d8be9a662da993 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Sep 26 11:42:38 2024 +0100 Add support for server and serverRemoveAppProvidedValues to h2 These configuration properties are inherited from the parent HTTP/1.1 connector. --- java/org/apache/coyote/http2/StreamProcessor.java | 13 ++ .../apache/coyote/http2/TestStreamProcessor.java | 146 +++++++++++++++++++++ webapps/docs/config/http2.xml | 2 + 3 files changed, 161 insertions(+) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index 6bde60d921..72c86020fd 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -242,6 +242,19 @@ class StreamProcessor extends AbstractProcessor { headers.addValue("date").setString(FastHttpDateFormat.getCurrentDate()); } + // Server header + if (protocol != null) { + String server = protocol.getHttp11Protocol().getServer(); + if (server == null) { + if (protocol.getHttp11Protocol().getServerRemoveAppProvidedValues()) { + headers.removeHeader("server"); + } + } else { + // server always overrides anything the app might set + headers.setValue("Server").setString(server); + } + } + // Exclude some HTTP header fields where the value is determined only // while generating the content as per section 9.3.2 of RFC 9110. if (coyoteRequest != null && coyoteRequest.method().equals("HEAD")) { diff --git a/test/org/apache/coyote/http2/TestStreamProcessor.java b/test/org/apache/coyote/http2/TestStreamProcessor.java index 4208ff5954..bfc4d8595b 100644 --- a/test/org/apache/coyote/http2/TestStreamProcessor.java +++ b/test/org/apache/coyote/http2/TestStreamProcessor.java @@ -653,4 +653,150 @@ public class TestStreamProcessor extends Http2TestBase { resp.getWriter().write("OK"); } } + + + @Test + public void testServerHeaderDefault() throws Exception { + enableHttp2(); + + Tomcat tomcat = getTomcatInstance(); + + Context ctxt = getProgrammaticRootContext(); + Tomcat.addServlet(ctxt, "simple", new SimpleServlet()); + ctxt.addServletMappingDecoded("/simple", "simple"); + Tomcat.addServlet(ctxt, "server", new ServerHeaderServlet()); + ctxt.addServletMappingDecoded("/server", "server"); + tomcat.start(); + + openClientConnection(); + doHttpUpgrade(); + sendClientPreface(); + validateHttp2InitialResponse(); + + // Disable overhead protection for window update as it breaks some tests + http2Protocol.setOverheadWindowUpdateThreshold(0); + + byte[] headersFrameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + + buildGetRequest(headersFrameHeader, headersPayload, null, 3, "/server"); + + // Write the headers + writeFrame(headersFrameHeader, headersPayload); + + parser.readFrame(); + parser.readFrame(); + + Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[200]\n" + + "3-Header-[server]-[TestServerApp]\n" + + "3-Header-[content-type]-[text/plain;charset=UTF-8]\n" + + "3-Header-[content-length]-[2]\n" + + "3-Header-[date]-[" + DEFAULT_DATE + "]\n" + "3-HeadersEnd\n" + "3-Body-2\n" + "3-EndOfStream\n", + output.getTrace()); + } + + + @Test + public void testServerHeaderRemove() throws Exception { + enableHttp2(); + + Tomcat tomcat = getTomcatInstance(); + + tomcat.getConnector().setProperty("serverRemoveAppProvidedValues", "true"); + + Context ctxt = getProgrammaticRootContext(); + Tomcat.addServlet(ctxt, "simple", new SimpleServlet()); + ctxt.addServletMappingDecoded("/simple", "simple"); + Tomcat.addServlet(ctxt, "server", new ServerHeaderServlet()); + ctxt.addServletMappingDecoded("/server", "server"); + tomcat.start(); + + openClientConnection(); + doHttpUpgrade(); + sendClientPreface(); + validateHttp2InitialResponse(); + + // Disable overhead protection for window update as it breaks some tests + http2Protocol.setOverheadWindowUpdateThreshold(0); + + byte[] headersFrameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + + buildGetRequest(headersFrameHeader, headersPayload, null, 3, "/server"); + + // Write the headers + writeFrame(headersFrameHeader, headersPayload); + + parser.readFrame(); + parser.readFrame(); + + Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[200]\n" + + "3-Header-[content-type]-[text/plain;charset=UTF-8]\n" + + "3-Header-[content-length]-[2]\n" + + "3-Header-[date]-[" + DEFAULT_DATE + "]\n" + "3-HeadersEnd\n" + "3-Body-2\n" + "3-EndOfStream\n", + output.getTrace()); + } + + + @Test + public void testServerHeaderForce() throws Exception { + enableHttp2(); + + Tomcat tomcat = getTomcatInstance(); + + Context ctxt = getProgrammaticRootContext(); + Tomcat.addServlet(ctxt, "simple", new SimpleServlet()); + ctxt.addServletMappingDecoded("/simple", "simple"); + Tomcat.addServlet(ctxt, "server", new ServerHeaderServlet()); + ctxt.addServletMappingDecoded("/server", "server"); + tomcat.start(); + + openClientConnection(); + doHttpUpgrade(); + sendClientPreface(); + validateHttp2InitialResponse(); + + /* + * This adds the server header to every response. Set this after the initial response has been validated to + * avoid having to update the validation code to account for the additional server header. + */ + tomcat.getConnector().setProperty("server", "TestServerForce"); + + // Disable overhead protection for window update as it breaks some tests + http2Protocol.setOverheadWindowUpdateThreshold(0); + + byte[] headersFrameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + + buildGetRequest(headersFrameHeader, headersPayload, null, 3, "/server"); + + // Write the headers + writeFrame(headersFrameHeader, headersPayload); + + parser.readFrame(); + parser.readFrame(); + + Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[200]\n" + + "3-Header-[server]-[TestServerForce]\n" + + "3-Header-[content-type]-[text/plain;charset=UTF-8]\n" + + "3-Header-[content-length]-[2]\n" + + "3-Header-[date]-[" + DEFAULT_DATE + "]\n" + "3-HeadersEnd\n" + "3-Body-2\n" + "3-EndOfStream\n", + output.getTrace()); + } + + + private static class ServerHeaderServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.addHeader("server", "TestServerApp"); + + resp.setCharacterEncoding(StandardCharsets.UTF_8); + resp.setContentType("text/plain"); + + resp.getWriter().write("OK"); + } + } } diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml index e3b763656c..8d918a5db9 100644 --- a/webapps/docs/config/http2.xml +++ b/webapps/docs/config/http2.xml @@ -244,6 +244,8 @@ <li>maxSavePostSize</li> <li>maxTrailerSize</li> <li>noCompressionUserAgents</li> + <li>server</li> + <li>serverRemoveAppProvidedValues</li> </ul> </subsection> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org