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 2017/05/24 13:00:47 UTC

svn commit: r1796054 - in /tomcat/trunk: java/javax/servlet/http/ java/org/apache/catalina/connector/ java/org/apache/coyote/ java/org/apache/coyote/ajp/ java/org/apache/coyote/http11/ java/org/apache/coyote/http2/ test/org/apache/catalina/filters/

Author: markt
Date: Wed May 24 13:00:47 2017
New Revision: 1796054

URL: http://svn.apache.org/viewvc?rev=1796054&view=rev
Log:
Servlet 4.0
Update API and implementation for reading trailer fields from the request

Modified:
    tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java
    tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java
    tomcat/trunk/java/org/apache/catalina/connector/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java
    tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
    tomcat/trunk/java/org/apache/coyote/ActionCode.java
    tomcat/trunk/java/org/apache/coyote/Request.java
    tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java
    tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
    tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java
    tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java

Modified: tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java (original)
+++ tomcat/trunk/java/javax/servlet/http/HttpServletRequest.java Wed May 24 13:00:47 2017
@@ -590,4 +590,23 @@ public interface HttpServletRequest exte
     public default Map<String,String> getTrailerFields() {
         return Collections.emptyMap();
     }
+
+    /**
+     * Are trailer fields ready to be read (there may still be no trailers to
+     * read). This method always returns {@code true} if the underlying protocol
+     * does not support trailer fields. Otherwise, {@code true} is returned once
+     * all of the following are true:
+     * <ul>
+     * <li>The application has ready all the request data and an EOF has been
+     *     received or the content-length is zero</li>
+     * <li>All trailer fields, if any, have been received</li>
+     * </ul>
+     *
+     * @return {@code true} if trailers are ready to be read
+     *
+     * @since Servlet 4.0
+     */
+    public default boolean isTrailerFieldsReady() {
+        return false;
+    }
 }

Modified: tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java (original)
+++ tomcat/trunk/java/javax/servlet/http/HttpServletRequestWrapper.java Wed May 24 13:00:47 2017
@@ -389,7 +389,8 @@ public class HttpServletRequestWrapper e
      * {@inheritDoc}
      * <p>
      * The default behavior of this method is to return
-     * {@link HttpServletRequest#newPushBuilder()} on the wrapped request object.
+     * {@link HttpServletRequest#newPushBuilder()} on the wrapped request
+     * object.
      *
      * @since Servlet 4.0
      */
@@ -402,7 +403,8 @@ public class HttpServletRequestWrapper e
      * {@inheritDoc}
      * <p>
      * The default behavior of this method is to return
-     * {@link HttpServletRequest#getTrailerFields()} on the wrapped request object.
+     * {@link HttpServletRequest#getTrailerFields()} on the wrapped request
+     * object.
      *
      * @since Servlet 4.0
      */
@@ -410,4 +412,19 @@ public class HttpServletRequestWrapper e
     public Map<String,String> getTrailerFields() {
         return this._getHttpServletRequest().getTrailerFields();
     }
+
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * The default behavior of this method is to return
+     * {@link HttpServletRequest#isTrailerFieldsReady()} on the wrapped request
+     * object.
+     *
+     * @since Servlet 4.0
+     */
+    @Override
+    public boolean isTrailerFieldsReady() {
+        return this._getHttpServletRequest().isTrailerFieldsReady();
+    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/connector/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/LocalStrings.properties?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/LocalStrings.properties Wed May 24 13:00:47 2017
@@ -56,6 +56,7 @@ coyoteRequest.filterAsyncSupportUnknown=
 coyoteRequest.maxPostSizeExceeded=The multi-part request contained parameter data (excluding uploaded files) that exceeded the limit for maxPostSize set on the associated connector
 coyoteRequest.noAsync=Unable to start async because the following classes in the processing chain do not support async [{0}]
 coyoteRequest.noMultipartConfig=Unable to process parts as no multi-part configuration has been provided
+coyoteRequest.trailersNotReady=It is illegal to call getTrailerFields() before isTrailerFieldsReady() has returned true
 
 coyoteResponse.encoding.invalid=The encoding [{0}] is not recognised by the JRE
 coyoteResponse.getOutputStream.ise=getWriter() has already been called for this response

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=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Wed May 24 13:00:47 2017
@@ -1953,18 +1953,22 @@ public class Request implements HttpServ
     // --------------------------------------------- HttpServletRequest Methods
 
     @Override
+    public boolean isTrailerFieldsReady() {
+        return coyoteRequest.isTrailerFieldsReady();
+    }
+
+
+    @Override
     public Map<String, String> getTrailerFields() {
+        if (!isTrailerFieldsReady()) {
+            throw new IllegalStateException(sm.getString("coyoteRequest.trailersNotReady"));
+        }
         Map<String,String> result = new HashMap<>();
         result.putAll(coyoteRequest.getTrailerFields());
         return result;
     }
 
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 4.0
-     */
     @Override
     public PushBuilder newPushBuilder() {
         AtomicBoolean result = new AtomicBoolean();
@@ -1977,11 +1981,6 @@ public class Request implements HttpServ
     }
 
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 3.1
-     */
     @SuppressWarnings("unchecked")
     @Override
     public <T extends HttpUpgradeHandler> T upgrade(

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=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/RequestFacade.java Wed May 24 13:00:47 2017
@@ -1068,11 +1068,13 @@ public class RequestFacade implements Ht
         return request.getAsyncContext();
     }
 
+
     @Override
     public DispatcherType getDispatcherType() {
         return request.getDispatcherType();
     }
 
+
     @Override
     public boolean authenticate(HttpServletResponse response)
     throws IOException, ServletException {
@@ -1096,31 +1098,25 @@ public class RequestFacade implements Ht
         return request.getParts();
     }
 
+
     @Override
     public Part getPart(String name) throws IllegalStateException, IOException,
             ServletException {
         return request.getPart(name);
     }
 
+
     public boolean getAllowTrace() {
         return request.getConnector().getAllowTrace();
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 3.1
-     */
+
     @Override
     public long getContentLengthLong() {
         return request.getContentLengthLong();
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 3.1
-     */
+
     @Override
     public <T extends HttpUpgradeHandler> T upgrade(
             Class<T> httpUpgradeHandlerClass) throws java.io.IOException, ServletException {
@@ -1128,22 +1124,18 @@ public class RequestFacade implements Ht
     }
 
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 4.0
-     */
     @Override
     public PushBuilder newPushBuilder() {
         return request.newPushBuilder();
     }
 
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since Servlet 4.0
-     */
+    @Override
+    public boolean isTrailerFieldsReady() {
+        return request.isTrailerFieldsReady();
+    }
+
+
     @Override
     public Map<String, String> getTrailerFields() {
         return request.getTrailerFields();

Modified: tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProcessor.java Wed May 24 13:00:47 2017
@@ -485,6 +485,13 @@ public abstract class AbstractProcessor
             doPush((Request) param);
             break;
         }
+
+        // Servlet 4.0 Trailers
+        case TRAILER_FIELDS_READY: {
+            AtomicBoolean result = (AtomicBoolean) param;
+            result.set(isTrailerFieldsReady());
+            break;
+        }
         }
     }
 
@@ -759,6 +766,9 @@ public abstract class AbstractProcessor
     }
 
 
+    protected abstract boolean isTrailerFieldsReady();
+
+
     /**
      * Flush any pending writes. Used during non-blocking writes to flush any
      * remaining data from a previous incomplete write.

Modified: tomcat/trunk/java/org/apache/coyote/ActionCode.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ActionCode.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ActionCode.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ActionCode.java Wed May 24 13:00:47 2017
@@ -245,5 +245,12 @@ public enum ActionCode {
     /**
      * Push a request on behalf of the client of the current request.
      */
-    PUSH_REQUEST
+    PUSH_REQUEST,
+
+    /**
+     * Are the request trailer fields ready to be read? Note that this returns
+     * true if it is known that request trailer fields are not supported so an
+     * empty collection of trailers can then be read.
+     */
+    TRAILER_FIELDS_READY
 }

Modified: tomcat/trunk/java/org/apache/coyote/Request.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Request.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Request.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Request.java Wed May 24 13:00:47 2017
@@ -197,6 +197,13 @@ public final class Request {
     }
 
 
+    public boolean isTrailerFieldsReady() {
+        AtomicBoolean result = new AtomicBoolean(false);
+        action(ActionCode.TRAILER_FIELDS_READY, result);
+        return result.get();
+    }
+
+
     public Map<String,String> getTrailerFields() {
         return trailerFields;
     }
@@ -670,5 +677,4 @@ public final class Request {
 
         return result;
     }
-
 }

Modified: tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AjpProcessor.java Wed May 24 13:00:47 2017
@@ -1190,6 +1190,14 @@ public class AjpProcessor extends Abstra
     }
 
 
+    @Override
+    protected boolean isTrailerFieldsReady() {
+        // AJP does not support trailers so return true so app can request the
+        // trailers and find out that there are none.
+        return true;
+    }
+
+
     /**
      * Read at least the specified amount of bytes, and place them
      * in the input buffer. Note that if any data is available to read then this

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java Wed May 24 13:00:47 2017
@@ -656,6 +656,16 @@ public class Http11InputBuffer implement
     }
 
 
+    boolean isChunking() {
+        for (int i = 0; i < lastActiveFilter; i++) {
+            if (activeFilters[i] == filterLibrary[Constants.CHUNKED_FILTER]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
     void init(SocketWrapperBase<?> socketWrapper) {
 
         wrapper = socketWrapper;

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=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Wed May 24 13:00:47 2017
@@ -1307,6 +1307,16 @@ public class Http11Processor extends Abs
     }
 
 
+    @Override
+    protected boolean isTrailerFieldsReady() {
+        if (inputBuffer.isChunking()) {
+            return inputBuffer.isFinished();
+        } else {
+            return true;
+        }
+    }
+
+
     /**
      * Trigger sendfile processing if required.
      *

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=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed May 24 13:00:47 2017
@@ -585,6 +585,12 @@ class Stream extends AbstractStream impl
     }
 
 
+    public boolean isTrailerFieldsReady() {
+        // Once EndOfStream has been received, canRead will be false
+        return !state.canRead();
+    }
+
+
     private static void push(final Http2UpgradeHandler handler, final Request request,
             final Stream stream) throws IOException {
         if (org.apache.coyote.Constants.IS_SECURITY_ENABLED) {

Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java Wed May 24 13:00:47 2017
@@ -218,6 +218,12 @@ class StreamProcessor extends AbstractPr
 
 
     @Override
+    protected boolean isTrailerFieldsReady() {
+        return stream.isTrailerFieldsReady();
+    }
+
+
+    @Override
     public final void recycle() {
         // StreamProcessor instances are not re-used.
         // Clear fields that can be cleared to aid GC and trigger NPEs if this

Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java?rev=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java Wed May 24 13:00:47 2017
@@ -136,6 +136,11 @@ class StreamStateMachine {
     }
 
 
+    final synchronized boolean canRead() {
+        return state.canRead();
+    }
+
+
     final synchronized boolean canWrite() {
         return state.canWrite();
     }
@@ -222,6 +227,10 @@ class StreamStateMachine {
             return canWrite || canRead;
         }
 
+        public boolean canRead() {
+            return canRead;
+        }
+
         public boolean canWrite() {
             return canWrite;
         }

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=1796054&r1=1796053&r2=1796054&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java (original)
+++ tomcat/trunk/test/org/apache/catalina/filters/TesterHttpServletRequest.java Wed May 24 13:00:47 2017
@@ -448,6 +448,11 @@ public class TesterHttpServletRequest im
     }
 
     @Override
+    public boolean isTrailerFieldsReady() {
+        throw new RuntimeException("Not implemented");
+    }
+
+    @Override
     public Map<String, String> getTrailerFields() {
         throw new RuntimeException("Not implemented");
     }



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