You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2022/08/01 16:15:23 UTC

[tomcat] branch main updated: Improve handling of HTTP TRACE requests

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 9eb6e2a4ad Improve handling of HTTP TRACE requests
9eb6e2a4ad is described below

commit 9eb6e2a4ad89fdbfa3b22680f03dcd7080811152
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Aug 1 17:15:08 2022 +0100

    Improve handling of HTTP TRACE requests
---
 java/jakarta/servlet/http/HttpServlet.java     | 17 +++++----
 test/jakarta/servlet/http/TestHttpServlet.java | 52 ++++++++++++++++++++++++++
 webapps/docs/changelog.xml                     |  8 ++++
 3 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/java/jakarta/servlet/http/HttpServlet.java b/java/jakarta/servlet/http/HttpServlet.java
index 8df75d69b4..ce85988633 100644
--- a/java/jakarta/servlet/http/HttpServlet.java
+++ b/java/jakarta/servlet/http/HttpServlet.java
@@ -622,9 +622,7 @@ public abstract class HttpServlet extends GenericServlet {
      * @exception ServletException  if the request for the
      *                                  TRACE cannot be handled
      */
-    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
-        throws ServletException, IOException
-    {
+    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         int responseLength;
 
@@ -632,12 +630,15 @@ public abstract class HttpServlet extends GenericServlet {
         StringBuilder buffer =
                 new StringBuilder("TRACE ").append(req.getRequestURI()).append(" ").append(req.getProtocol());
 
-        Enumeration<String> reqHeaderEnum = req.getHeaderNames();
+        Enumeration<String> reqHeaderNames = req.getHeaderNames();
 
-        while( reqHeaderEnum.hasMoreElements() ) {
-            String headerName = reqHeaderEnum.nextElement();
-            buffer.append(CRLF).append(headerName).append(": ")
-                .append(req.getHeader(headerName));
+        while (reqHeaderNames.hasMoreElements()) {
+            String headerName = reqHeaderNames.nextElement();
+            Enumeration<String> headerValues = req.getHeaders(headerName);
+            while (headerValues.hasMoreElements()) {
+                String headerValue = headerValues.nextElement();
+                buffer.append(CRLF).append(headerName).append(": ").append(headerValue);
+            }
         }
 
         buffer.append(CRLF);
diff --git a/test/jakarta/servlet/http/TestHttpServlet.java b/test/jakarta/servlet/http/TestHttpServlet.java
index a9b11cef6f..3697960245 100644
--- a/test/jakarta/servlet/http/TestHttpServlet.java
+++ b/test/jakarta/servlet/http/TestHttpServlet.java
@@ -40,6 +40,7 @@ import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
+import org.apache.tomcat.util.net.TesterSupport.SimpleServlet;
 
 public class TestHttpServlet extends TomcatBaseTest {
 
@@ -293,6 +294,57 @@ public class TestHttpServlet extends TomcatBaseTest {
     }
 
 
+    @Test
+    public void testTrace() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        tomcat.getConnector().setAllowTrace(true);
+
+        // No file system docBase required
+        StandardContext ctx = (StandardContext) tomcat.addContext("", null);
+
+        // Map the test Servlet
+        Tomcat.addServlet(ctx, "servlet", new SimpleServlet());
+        ctx.addServletMappingDecoded("/", "servlet");
+
+        tomcat.start();
+
+        TraceClient client = new TraceClient();
+        client.setPort(getPort());
+        client.setRequest(new String[] {
+                "TRACE / HTTP/1.1" + SimpleHttpClient.CRLF +
+                "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+                "X-aaa: a1, a2" + SimpleHttpClient.CRLF +
+                "X-aaa: a3" + SimpleHttpClient.CRLF +
+                SimpleHttpClient.CRLF});
+        client.setUseContentLength(true);
+
+        client.connect();
+        client.sendRequest();
+        client.readResponse(true);
+
+        String body = client.getResponseBody();
+
+        System.out.println(body);
+
+        Assert.assertTrue(client.getResponseLine(), client.isResponse200());
+        // Far from perfect but good enough
+        Assert.assertTrue(body.contains("a1"));
+        Assert.assertTrue(body.contains("a2"));
+        Assert.assertTrue(body.contains("a3"));
+
+        client.disconnect();
+    }
+
+
+    private static final class TraceClient extends SimpleHttpClient {
+
+        @Override
+        public boolean isResponseBodyOK() {
+            return true;
+        }
+    }
+
+
     private class Client extends SimpleHttpClient {
 
         public Client(String request, boolean isHttp09) {
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 21ae993bb4..2c856cc4d3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -105,6 +105,14 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 10.1.0-M18 (markt)" rtext="in development">
+  <subsection name="Catalina">
+    <changelog>
+      <fix>
+        Correct handling of HTTP TRACE requests where there are multiple
+        instances of an HTTP header with the same name. (markt)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Coyote">
     <changelog>
       <fix>


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