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 2013/09/11 16:07:31 UTC

svn commit: r1521854 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/coyote/ajp/ java/org/apache/coyote/http11/ test/org/apache/coyote/ajp/ test/org/apache/coyote/http11/

Author: markt
Date: Wed Sep 11 14:07:31 2013
New Revision: 1521854

URL: http://svn.apache.org/r1521854
Log:
Better adherence to RFC2616 for content-length headers

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
    tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
    tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/TestAbstractHttp11Processor.java

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1521829

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1521854&r1=1521853&r2=1521854&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Wed Sep 11 14:07:31 2013
@@ -25,6 +25,8 @@ import java.security.cert.CertificateFac
 import java.security.cert.X509Certificate;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import javax.servlet.http.HttpServletResponse;
+
 import org.apache.coyote.AbstractProcessor;
 import org.apache.coyote.ActionCode;
 import org.apache.coyote.AsyncContextCallback;
@@ -691,6 +693,7 @@ public abstract class AbstractAjpProcess
         // Set this every time in case limit has been changed via JMX
         headers.setLimit(endpoint.getMaxHeaderCount());
 
+        boolean contentLengthSet = false;
         int hCount = requestHeaderMessage.getInt();
         for(int i = 0 ; i < hCount ; i++) {
             String hName = null;
@@ -725,8 +728,15 @@ public abstract class AbstractAjpProcess
 
             if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
                     (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
-                // just read the content-length header, so set it
-                request.setContentLength(vMB.getLong());
+                long cl = vMB.getLong();
+                if (contentLengthSet) {
+                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                    error = true;
+                } else {
+                    contentLengthSet = true;
+                    // Set the content-length header for the request
+                    request.setContentLength(cl);
+                }
             } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
                     (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
                 // just read the content-type header, so set it

Modified: tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1521854&r1=1521853&r2=1521854&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Wed Sep 11 14:07:31 2013
@@ -1296,10 +1296,20 @@ public abstract class AbstractHttp11Proc
 
         // Parse content-length header
         long contentLength = request.getContentLengthLong();
-        if (contentLength >= 0 && !contentDelimitation) {
-            getInputBuffer().addActiveFilter
-                (inputFilters[Constants.IDENTITY_FILTER]);
-            contentDelimitation = true;
+        if (contentLength >= 0) {
+            if (contentDelimitation) {
+                // contentDelimitation being true at this point indicates that
+                // chunked encoding is being used but chunked encoding should
+                // not be used with a content length. RFC 2616, section 4.4,
+                // bullet 3 states Content-Length must be ignored in this case -
+                // so remove it.
+                headers.removeHeader("content-length");
+                request.setContentLength(-1);
+            } else {
+                getInputBuffer().addActiveFilter
+                        (inputFilters[Constants.IDENTITY_FILTER]);
+                contentDelimitation = true;
+            }
         }
 
         MessageBytes valueMB = headers.getValue("host");

Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java?rev=1521854&r1=1521853&r2=1521854&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java Wed Sep 11 14:07:31 2013
@@ -98,9 +98,20 @@ public class TestAbstractAjpProcessor ex
         ajpClient.disconnect();
     }
 
+    @Test
+    public void testPost() throws Exception {
+        doTestPost(false, HttpServletResponse.SC_OK);
+    }
+
 
     @Test
-    public void testSimplePost() throws Exception {
+    public void testPostMultipleContentLength() throws Exception {
+        // Multiple content lengths
+        doTestPost(true, HttpServletResponse.SC_BAD_REQUEST);
+    }
+
+
+    public void doTestPost(boolean multipleCL, int expectedStatus) throws Exception {
 
         Tomcat tomcat = getTomcatInstance();
 
@@ -119,6 +130,9 @@ public class TestAbstractAjpProcessor ex
         TesterAjpMessage forwardMessage =
                 ajpClient.createForwardMessage("/echo-params.jsp", 4);
         forwardMessage.addHeader(0xA008, "9");
+        if (multipleCL) {
+            forwardMessage.addHeader(0xA008, "99");
+        }
         forwardMessage.addHeader(0xA007, "application/x-www-form-urlencoded");
         forwardMessage.end();
 
@@ -128,15 +142,20 @@ public class TestAbstractAjpProcessor ex
         TesterAjpMessage responseHeaders =
                 ajpClient.sendMessage(forwardMessage, bodyMessage);
 
-        // Expect 3 messages: headers, body, end
-        validateResponseHeaders(responseHeaders, 200);
-        // Skip the body
-        TesterAjpMessage responseBody = ajpClient.readMessage();
-        validateResponseBody(responseBody, "test - data");
-        validateResponseEnd(ajpClient.readMessage(), true);
+        validateResponseHeaders(responseHeaders, expectedStatus);
+        if (expectedStatus == HttpServletResponse.SC_OK) {
+            // Expect 3 messages: headers, body, end for a valid request
+            TesterAjpMessage responseBody = ajpClient.readMessage();
+            validateResponseBody(responseBody, "test - data");
+            validateResponseEnd(ajpClient.readMessage(), true);
+
+            // Double check the connection is still open
+            validateCpong(ajpClient.cping());
+        } else {
+            // Expect 2 messages: headers, end for an invalid request
+            validateResponseEnd(ajpClient.readMessage(), false);
+        }
 
-        // Double check the connection is still open
-        validateCpong(ajpClient.cping());
 
         ajpClient.disconnect();
     }

Modified: tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/TestAbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/TestAbstractHttp11Processor.java?rev=1521854&r1=1521853&r2=1521854&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/TestAbstractHttp11Processor.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/coyote/http11/TestAbstractHttp11Processor.java Wed Sep 11 14:07:31 2013
@@ -101,6 +101,54 @@ public class TestAbstractHttp11Processor
 
 
     @Test
+    public void testWithTEChunked() throws Exception {
+        doTestWithTEChunked(false);
+    }
+
+
+    @Test
+    public void testWithTEChunkedWithCL() throws Exception {
+        // Should be ignored
+        doTestWithTEChunked(true);
+    }
+
+
+    private void doTestWithTEChunked(boolean withCL)
+            throws Exception {
+
+        Tomcat tomcat = getTomcatInstance();
+
+        // Use the normal Tomcat ROOT context
+        File root = new File("test/webapp-3.0");
+        tomcat.addWebapp("", root.getAbsolutePath());
+
+        tomcat.start();
+
+        String request =
+            "POST /echo-params.jsp HTTP/1.1" + SimpleHttpClient.CRLF +
+            "Host: any" + SimpleHttpClient.CRLF +
+            (withCL ? "Content-length: 1" + SimpleHttpClient.CRLF : "") +
+            "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
+            "Content-Type: application/x-www-form-urlencoded" +
+                    SimpleHttpClient.CRLF +
+            "Connection: close" + SimpleHttpClient.CRLF +
+            SimpleHttpClient.CRLF +
+            "9" + SimpleHttpClient.CRLF +
+            "test=data" + SimpleHttpClient.CRLF +
+            "0" + SimpleHttpClient.CRLF +
+            SimpleHttpClient.CRLF;
+
+        Client client = new Client(tomcat.getConnector().getLocalPort());
+        client.setRequest(new String[] {request});
+
+        client.connect();
+        client.processRequest();
+        assertTrue(client.isResponse200());
+        assertTrue(client.getResponseBody().contains("test - data"));
+    }
+
+
+    @Test
     public void testWithTEIdentity() throws Exception {
         Tomcat tomcat = getTomcatInstance();
 



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