Author: markt
Date: Tue May  2 18:48:20 2017
New Revision: 1793573

URL: http://svn.apache.org/viewvc?rev=1793573&view=rev
Log:
Update the Servlet 4.0 implementation to add support for obtaining trailer 
fields from chunked HTTP requests.

Modified:
    tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java
    tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java
    tomcat/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java
    tomcat/trunk/java/org/apache/coyote/Request.java
    tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java
    tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java
    
tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
    tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java (original)
+++ tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java Tue May  2 
18:48:20 2017
@@ -20,6 +20,7 @@ package javax.servlet.http;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.Map;
 
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
@@ -575,4 +576,13 @@ public interface HttpServletRequest exte
      */
     public <T extends HttpUpgradeHandler> T upgrade(
             Class<T> httpUpgradeHandlerClass) throws java.io.IOException, 
ServletException;
+
+    /**
+     * Obtain a Map of the trailer fields that is not backed by the request
+     * object.
+     *
+     * @return A Map of the received trailer fields with all keys lower case
+     *         or an empty Map if no trailers are present
+     */
+    public Map<String,String> getTrailerFields();
 }

Modified: tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java 
(original)
+++ tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java Tue May 
 2 18:48:20 2017
@@ -19,6 +19,7 @@ package javax.servlet.http;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.Map;
 
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequestWrapper;
@@ -396,4 +397,17 @@ public class HttpServletRequestWrapper e
     public PushBuilder newPushBuilder() {
         return this._getHttpServletRequest().newPushBuilder();
     }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * The default behavior of this method is to return
+     * {@link HttpServletRequest#newPushBuilder()} on the wrapped request 
object.
+     *
+     * @since Servlet 4.0
+     */
+    @Override
+    public Map<String,String> getTrailerFields() {
+        return this._getHttpServletRequest().getTrailerFields();
+    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Tue May  2 
18:48:20 2017
@@ -1930,6 +1930,14 @@ public class Request implements HttpServ
 
     // --------------------------------------------- HttpServletRequest Methods
 
+    @Override
+    public Map<String, String> getTrailerFields() {
+        Map<String,String> result = new HashMap<>();
+        result.putAll(coyoteRequest.getTrailerFields());
+        return result;
+    }
+
+
     /**
      * {@inheritDoc}
      *

Modified: tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java Tue May  
2 18:48:20 2017
@@ -1137,4 +1137,15 @@ public class RequestFacade implements Ht
     public PushBuilder newPushBuilder() {
         return request.newPushBuilder();
     }
+
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since Servlet 4.0
+     */
+    @Override
+    public Map<String, String> getTrailerFields() {
+        return request.getTrailerFields();
+    }
 }

Modified: tomcat/trunk/java/org/apache/coyote/Request.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Request.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Request.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Request.java Tue May  2 18:48:20 2017
@@ -96,6 +96,7 @@ public final class Request {
     private final MessageBytes localAddrMB = MessageBytes.newInstance();
 
     private final MimeHeaders headers = new MimeHeaders();
+    private final Map<String,String> trailerFields = new HashMap<>();
 
 
     /**
@@ -193,12 +194,17 @@ public final class Request {
     }
 
 
+    public Map<String,String> getTrailerFields() {
+        return trailerFields;
+    }
+
+
     public UDecoder getURLDecoder() {
         return urlDecoder;
     }
 
-    // -------------------- Request data --------------------
 
+    // -------------------- Request data --------------------
 
     public MessageBytes scheme() {
         return schemeMB;

Modified: 
tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 
Tue May  2 18:48:20 2017
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.coyote.InputBuffer;
@@ -29,8 +30,6 @@ import org.apache.coyote.http11.Constant
 import org.apache.coyote.http11.InputFilter;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.net.ApplicationBufferHandler;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -435,7 +434,7 @@ public class ChunkedInputFilter implemen
 
     private boolean parseHeader() throws IOException {
 
-        MimeHeaders headers = request.getMimeHeaders();
+        Map<String,String> headers = request.getTrailerFields();
 
         byte chr = 0;
 
@@ -579,12 +578,14 @@ public class ChunkedInputFilter implemen
         String headerName = new String(trailingHeaders.getBytes(), startPos,
                 colonPos - startPos, StandardCharsets.ISO_8859_1);
 
-        if 
(allowedTrailerHeaders.contains(headerName.toLowerCase(Locale.ENGLISH))) {
-            MessageBytes headerValue = headers.addValue(headerName);
+        headerName = headerName.toLowerCase(Locale.ENGLISH);
 
-            // Set the header value
-            headerValue.setBytes(trailingHeaders.getBytes(), colonPos,
-                    lastSignificantChar - colonPos);
+        if (allowedTrailerHeaders.contains(headerName)) {
+
+            String value = new String(trailingHeaders.getBytes(), colonPos,
+                    lastSignificantChar - colonPos, 
StandardCharsets.ISO_8859_1);
+
+            headers.put(headerName, value);
         }
 
         return true;

Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Tue May  2 18:48:20 
2017
@@ -345,8 +345,13 @@ class Stream extends AbstractStream impl
                 headerStateErrorMsg = 
sm.getString("stream.header.unknownPseudoHeader",
                         getConnectionId(), getIdentifier(), name);
             }
-            // Assume other HTTP header
-            coyoteRequest.getMimeHeaders().addValue(name).setString(value);
+
+            if (headerState == HEADER_STATE_TRAILER) {
+                // HTTP/2 headers are already always lower case
+                coyoteRequest.getTrailerFields().put(name, value);
+            } else {
+                coyoteRequest.getMimeHeaders().addValue(name).setString(value);
+            }
         }
         }
     }

Modified: 
tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java 
Tue May  2 18:48:20 2017
@@ -446,4 +446,9 @@ public class TesterHttpServletRequest im
     public PushBuilder newPushBuilder() {
         throw new RuntimeException("Not implemented");
     }
+
+    @Override
+    public Map<String, String> getTrailerFields() {
+        throw new RuntimeException("Not implemented");
+    }
 }

Modified: 
tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- 
tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java 
(original)
+++ 
tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java 
Tue May  2 18:48:20 2017
@@ -105,7 +105,7 @@ public class TestChunkedInputFilter exte
         Context ctx = tomcat.addContext("", null);
 
         // Configure allowed trailer headers
-        tomcat.getConnector().setProperty("allowedTrailerHeaders", 
"X-Trailer1,X-Trailer2");
+        tomcat.getConnector().setProperty("allowedTrailerHeaders", 
"x-trailer1,x-trailer2");
 
         EchoHeaderServlet servlet = new EchoHeaderServlet(expectPass);
         Tomcat.addServlet(ctx, "servlet", servlet);
@@ -478,7 +478,7 @@ public class TestChunkedInputFilter exte
 
         private void dumpHeader(String headerName, HttpServletRequest req,
                 PrintWriter pw) {
-            String value = req.getHeader(headerName);
+            String value = req.getTrailerFields().get(headerName);
             if (value == null) {
                 value = "null";
             }

Modified: tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Tue May  2 
18:48:20 2017
@@ -72,7 +72,7 @@ public abstract class Http2TestBase exte
         EMPTY_HTTP2_SETTINGS_HEADER = "HTTP2-Settings: " + 
Base64.encodeBase64String(empty) + "\r\n";
     }
 
-    protected static final String TRAILER_HEADER_NAME = "X-TrailerTest";
+    protected static final String TRAILER_HEADER_NAME = "x-trailertest";
     protected static final String TRAILER_HEADER_VALUE = "test";
 
     private Socket s;
@@ -1091,7 +1091,7 @@ public abstract class Http2TestBase exte
             IOTools.flow(bais, resp.getOutputStream());
 
             // Check for trailer headers
-            String trailerValue = req.getHeader(TRAILER_HEADER_NAME);
+            String trailerValue = 
req.getTrailerFields().get(TRAILER_HEADER_NAME);
             if (trailerValue != null) {
                 
resp.getOutputStream().write(trailerValue.getBytes(StandardCharsets.UTF_8));
             }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1793573&r1=1793572&r2=1793573&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue May  2 18:48:20 2017
@@ -104,6 +104,10 @@
         custom error page located below <code>WEB-INF</code>, ensure that the
         target error page is displayed rather than a 404 response. (markt)
       </fix>
+      <update>
+        Update the Servlet 4.0 implementation to add support for obtaining
+        trailer fields from chunked HTTP requests. (markt)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to