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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org