tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r1746649 - in /tomcat/trunk: java/org/apache/coyote/http11/Http11Processor.java test/org/apache/coyote/http11/TestHttp11Processor.java webapps/docs/changelog.xml
Date Thu, 02 Jun 2016 22:37:49 GMT
Author: markt
Date: Thu Jun  2 22:37:48 2016
New Revision: 1746649

URL: http://svn.apache.org/viewvc?rev=1746649&view=rev
Log:
If an async dispatch results in the completion of request processing, ensure that any remaining
requets body is swallowed before starting the processing of the next request else the remaining
body may be read as the start of the next request leading to a 400 response.

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
    tomcat/trunk/test/org/apache/coyote/http11/TestHttp11Processor.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1746649&r1=1746648&r2=1746649&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Thu Jun  2 22:37:48 2016
@@ -1727,6 +1727,7 @@ public class Http11Processor extends Abs
         if (!keepAlive) {
             return SocketState.CLOSED;
         } else {
+            endRequest();
             inputBuffer.nextRequest();
             outputBuffer.nextRequest();
             if (socketWrapper.isReadPending()) {

Modified: tomcat/trunk/test/org/apache/coyote/http11/TestHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http11/TestHttp11Processor.java?rev=1746649&r1=1746648&r2=1746649&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http11/TestHttp11Processor.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http11/TestHttp11Processor.java Thu Jun  2 22:37:48
2016
@@ -16,11 +16,18 @@
  */
 package org.apache.coyote.http11;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.io.Reader;
 import java.io.Writer;
+import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.net.SocketAddress;
 import java.nio.CharBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -31,6 +38,7 @@ import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
 import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
@@ -842,4 +850,99 @@ public class TestHttp11Processor extends
                 throws ServletException, IOException {
         }
     }
+
+
+    /*
+     * Tests what happens if a request is completed during a dispatch but the
+     * request body has not been fully read.
+     */
+    @Test
+    public void testRequestBodySwallowing() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+
+        // No file system docBase required
+        Context ctx = tomcat.addContext("", null);
+
+        SempahoreServlet servlet = new SempahoreServlet();
+        Wrapper w = Tomcat.addServlet(ctx, "Test", servlet);
+        w.setAsyncSupported(true);
+        ctx.addServletMapping("/test", "Test");
+
+        tomcat.start();
+
+        // Hand-craft the client so we have complete control over the timing
+        SocketAddress addr = new InetSocketAddress("localhost", getPort());
+        Socket socket = new Socket();
+        socket.setSoTimeout(300000);
+        socket.connect(addr,300000);
+        OutputStream os = socket.getOutputStream();
+        Writer writer = new OutputStreamWriter(os, "ISO-8859-1");
+        InputStream is = socket.getInputStream();
+        Reader r = new InputStreamReader(is, "ISO-8859-1");
+        BufferedReader reader = new BufferedReader(r);
+
+        // Write the headers
+        writer.write("POST /test HTTP/1.1\r\n");
+        writer.write("Host: localhost:8080\r\n");
+        writer.write("Transfer-Encoding: chunked\r\n");
+        writer.write("\r\n");
+        writer.flush();
+
+        validateResponse(reader);
+
+        // Write the request body
+        writer.write("2\r\n");
+        writer.write("AB\r\n");
+        writer.write("0\r\n");
+        writer.write("\r\n");
+        writer.flush();
+
+        // Write the 2nd request
+        writer.write("POST /test HTTP/1.1\r\n");
+        writer.write("Host: localhost:8080\r\n");
+        writer.write("Transfer-Encoding: chunked\r\n");
+        writer.write("\r\n");
+        writer.flush();
+
+        // Read the 2nd response
+        validateResponse(reader);
+
+        // Write the 2nd request body
+        writer.write("2\r\n");
+        writer.write("AB\r\n");
+        writer.write("0\r\n");
+        writer.write("\r\n");
+        writer.flush();
+
+        // Done
+        socket.close();
+    }
+
+
+    private void validateResponse(BufferedReader reader) throws IOException {
+        // First line has the response code and should always be 200
+        String line = reader.readLine();
+        Assert.assertEquals("HTTP/1.1 200 ", line);
+        while (!"OK".equals(line)) {
+            line = reader.readLine();
+        }
+    }
+
+
+    private static class SempahoreServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+            if (DispatcherType.ASYNC.equals(req.getDispatcherType())) {
+                resp.setContentType("text/plain");
+                resp.setCharacterEncoding("UTF-8");
+                resp.getWriter().write("OK\n");
+            } else {
+                req.startAsync().dispatch();
+            }
+        }
+    }
 }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1746649&r1=1746648&r2=1746649&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Thu Jun  2 22:37:48 2016
@@ -109,6 +109,12 @@
         <code>WriteListener.onError()</code> or
         <code>AsycnListener.onError()</code>) is called. (markt)
       </fix>
+      <fix>
+       If an async dispatch results in the completion of request processing,
+       ensure that any remaining requets body is swallowed before starting the
+       processing of the next request else the remaining body may be read as the
+       start of the next request leading to a 400 response. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">



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


Mime
View raw message