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 8e786a8eda Update the default HEAD response to exclude payload headers
8e786a8eda is described below

commit 8e786a8eda188426dff97e9c997dfceb4eb469c2
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jan 19 20:40:10 2023 +0000

    Update the default HEAD response to exclude payload headers
    
    First explicitly allowed in RFC 7231 and also in the current RFC 9110
---
 java/org/apache/coyote/http11/Http11Processor.java | 10 +++++++-
 java/org/apache/coyote/http2/StreamProcessor.java  |  6 +++++
 .../servlet/http/HttpServletDoHeadBaseTest.java    | 27 +++++++++++++++++-----
 test/jakarta/servlet/http/TestHttpServlet.java     | 20 ++++++++++++++--
 webapps/docs/changelog.xml                         |  4 ++++
 5 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11Processor.java 
b/java/org/apache/coyote/http11/Http11Processor.java
index c27ff911f4..951d276593 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -916,7 +916,8 @@ public class Http11Processor extends AbstractProcessor {
         }
 
         MessageBytes methodMB = request.method();
-        if (methodMB.equals("HEAD")) {
+        boolean head = methodMB.equals("HEAD");
+        if (head) {
             // No entity body
             outputBuffer.addActiveFilter
                 (outputFilters[Constants.VOID_FILTER]);
@@ -1056,6 +1057,13 @@ public class Http11Processor extends AbstractProcessor {
             headers.setValue("Server").setString(server);
         }
 
+        if (head) {
+            headers.removeHeader("content-length");
+            headers.removeHeader("content-range");
+            headers.removeHeader("trailer");
+            headers.removeHeader("transfer-encoding");
+        }
+
         // Build the response header
         try {
             outputBuffer.sendStatus();
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java 
b/java/org/apache/coyote/http2/StreamProcessor.java
index 3afda9037b..acd9dce237 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -220,6 +220,12 @@ class StreamProcessor extends AbstractProcessor {
         if (statusCode >= 200 && headers.getValue("date") == null) {
             
headers.addValue("date").setString(FastHttpDateFormat.getCurrentDate());
         }
+
+        // Remove payload headers for HEAD requests
+        if (coyoteRequest != null && 
"HEAD".equals(coyoteRequest.method().toString())) {
+            headers.removeHeader("content-length");
+            headers.removeHeader("content-range");
+        }
     }
 
 
diff --git a/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java 
b/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
index 21a962d48d..e513be2430 100644
--- a/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
+++ b/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java
@@ -95,7 +95,15 @@ public class HttpServletDoHeadBaseTest extends Http2TestBase 
{
         rc = headUrl(path, out, headHeaders);
         Assert.assertEquals(HttpServletResponse.SC_OK, rc);
 
-        // Headers should be the same (apart from Date)
+        // Headers should be the same part from:
+        // - Date header may be different
+        // - HEAD requests don't include payload headers
+        //   (RFC 7231, section 4.3.2)
+        getHeaders.remove("content-length");
+        getHeaders.remove("content-range");
+        getHeaders.remove("trailer");
+        getHeaders.remove("transfer-encoding");
+
         Assert.assertEquals(getHeaders.size(), headHeaders.size());
         for (Map.Entry<String, List<String>> getHeader : 
getHeaders.entrySet()) {
             String headerName = getHeader.getKey();
@@ -158,15 +166,22 @@ public class HttpServletDoHeadBaseTest extends 
Http2TestBase {
             String[] headHeaders = traceHead.split("\n");
 
             int i = 0;
+            int j = 0;
             for (; i < getHeaders.length; i++) {
-                // Headers should be the same, ignoring the first character 
which is the steam ID
-                Assert.assertEquals(getHeaders[i] + "\n" + traceGet + 
traceHead, '3', getHeaders[i].charAt(0));
-                Assert.assertEquals(headHeaders[i] + "\n" + traceGet + 
traceHead, '5', headHeaders[i].charAt(0));
-                Assert.assertEquals(traceGet + traceHead, 
getHeaders[i].substring(1), headHeaders[i].substring(1));
+                // Ignore payload headers
+                if (getHeaders[i].contains("content-length") || 
getHeaders[i].contains("content-range") ) {
+                    // Skip
+                } else {
+                    // Headers should be the same, ignoring the first 
character which is the steam ID
+                    Assert.assertEquals(getHeaders[i] + "\n" + traceGet + 
traceHead, '3', getHeaders[i].charAt(0));
+                    Assert.assertEquals(headHeaders[j] + "\n" + traceGet + 
traceHead, '5', headHeaders[j].charAt(0));
+                    Assert.assertEquals(traceGet + traceHead, 
getHeaders[i].substring(1), headHeaders[j].substring(1));
+                    j++;
+                }
             }
 
             // Stream 5 should have one more trace entry
-            Assert.assertEquals("5-EndOfStream", headHeaders[i]);
+            Assert.assertEquals("5-EndOfStream", headHeaders[j]);
         } catch (Exception t) {
             System.out.println(debug.toString());
             throw t;
diff --git a/test/jakarta/servlet/http/TestHttpServlet.java 
b/test/jakarta/servlet/http/TestHttpServlet.java
index e12bcd54be..077467454e 100644
--- a/test/jakarta/servlet/http/TestHttpServlet.java
+++ b/test/jakarta/servlet/http/TestHttpServlet.java
@@ -45,6 +45,10 @@ import 
org.apache.tomcat.util.net.TesterSupport.SimpleServlet;
 
 public class TestHttpServlet extends TomcatBaseTest {
 
+    /*
+     * Nature of test has changed from original bug report since content-length
+     * is no longer returned for HEAD requests as allowed by RFC 7231.
+     */
     @Test
     public void testBug53454() throws Exception {
         Tomcat tomcat = getTomcatInstance();
@@ -64,8 +68,7 @@ public class TestHttpServlet extends TomcatBaseTest {
                resHeaders);
 
         Assert.assertEquals(HttpServletResponse.SC_OK, rc);
-        Assert.assertEquals(LargeBodyServlet.RESPONSE_LENGTH,
-                resHeaders.get("Content-Length").get(0));
+        Assert.assertNull(resHeaders.get("Content-Length"));
     }
 
 
@@ -178,6 +181,7 @@ public class TestHttpServlet extends TomcatBaseTest {
 
         int rc = getUrl(path, out, getHeaders);
         Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+        removePayloadHeaders(getHeaders);
         out.recycle();
 
         Map<String,List<String>> headHeaders = new HashMap<>();
@@ -204,6 +208,18 @@ public class TestHttpServlet extends TomcatBaseTest {
     }
 
 
+    /*
+     * Removes headers that are not expected to appear in the response to the
+     * equivalent HEAD request.
+     */
+    private void removePayloadHeaders(Map<String,List<String>> headers) {
+        headers.remove("content-length");
+        headers.remove("content-range");
+        headers.remove("trailer");
+        headers.remove("transfer-encoding");
+    }
+
+
     @Test
     public void testDoOptions() throws Exception {
         doTestDoOptions(new OptionsServlet(), "GET, HEAD, OPTIONS");
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 7570715faa..9fd2f679a3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -125,6 +125,10 @@
         Implement the new Servlet API methods for setting character encodings
         that accept {@code Charset} objects. (markt)
       </add>
+      <update>
+        The default HEAD response no longer includes the payload HTTP header
+        fields as per section 9.3.2 of RFC 9110. (markt)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to