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 2015/03/13 11:02:34 UTC
svn commit: r1666386 - in /tomcat/trunk: java/org/apache/coyote/http11/
java/org/apache/coyote/http11/filters/ test/org/apache/coyote/http11/filters/
Author: markt
Date: Fri Mar 13 10:02:34 2015
New Revision: 1666386
URL: http://svn.apache.org/r1666386
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57570
Make processing of trailer headers for chunked input optional.
Trailer headers to process must be added to the allowedTrailerHeader list or they will be ignored
Modified:
tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
tomcat/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java
tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java?rev=1666386&r1=1666385&r2=1666386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Fri Mar 13 10:02:34 2015
@@ -18,6 +18,13 @@ package org.apache.coyote.http11;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpUpgradeHandler;
@@ -196,6 +203,59 @@ public abstract class AbstractHttp11Prot
}
+ /**
+ * The names of headers that are allowed to be sent via a trailer when using
+ * chunked encoding. They are stored in lower case.
+ */
+ private Set<String> allowedTrailerHeaders =
+ Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+ public void setAllowedTrailerHeaders(String commaSeparatedHeaders) {
+ // Jump through some hoops so we don't end up with an empty set while
+ // doing updates.
+ Set<String> toRemove = new HashSet<>();
+ toRemove.addAll(allowedTrailerHeaders);
+ if (commaSeparatedHeaders != null) {
+ String[] headers = commaSeparatedHeaders.split(",");
+ for (String header : headers) {
+ String trimmedHeader = header.trim().toLowerCase(Locale.ENGLISH);
+ if (toRemove.contains(trimmedHeader)) {
+ toRemove.remove(trimmedHeader);
+ } else {
+ allowedTrailerHeaders.add(trimmedHeader);
+ }
+ }
+ allowedTrailerHeaders.removeAll(toRemove);
+ }
+ }
+ public String getAllowedTrailerHeaders() {
+ // Chances of a size change between these lines are small enough that a
+ // sync is unnecessary.
+ List<String> copy = new ArrayList<>(allowedTrailerHeaders.size());
+ copy.addAll(allowedTrailerHeaders);
+ StringBuilder result = new StringBuilder();
+ boolean first = true;
+ for (String header : copy) {
+ if (first) {
+ first = false;
+ } else {
+ result.append(',');
+ }
+ result.append(header);
+ }
+ return result.toString();
+ }
+ public void addAllowedTrailerHeader(String header) {
+ if (header != null) {
+ allowedTrailerHeaders.add(header.trim().toLowerCase(Locale.ENGLISH));
+ }
+ }
+ public void removeAllowedTrailerHeader(String header) {
+ if (header != null) {
+ allowedTrailerHeaders.remove(header.trim().toLowerCase(Locale.ENGLISH));
+ }
+ }
+
+
// ------------------------------------------------ HTTP specific properties
// ------------------------------------------ passed through to the EndPoint
@@ -271,8 +331,8 @@ public abstract class AbstractHttp11Prot
@Override
public Http11Processor createProcessor() {
Http11Processor processor = new Http11Processor(
- proto.getMaxHttpHeaderSize(), proto.getEndpoint(),
- proto.getMaxTrailerSize(), proto.getMaxExtensionSize(),
+ proto.getMaxHttpHeaderSize(), proto.getEndpoint(), proto.getMaxTrailerSize(),
+ proto.allowedTrailerHeaders, proto.getMaxExtensionSize(),
proto.getMaxSwallowSize());
proto.configureProcessor(processor);
register(processor);
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=1666386&r1=1666385&r2=1666386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Fri Mar 13 10:02:34 2015
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.Locale;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
@@ -238,8 +239,8 @@ public class Http11Processor extends Abs
protected SSLSupport sslSupport;
- public Http11Processor(int maxHttpHeaderSize, AbstractEndpoint<?> endpoint,
- int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
+ public Http11Processor(int maxHttpHeaderSize, AbstractEndpoint<?> endpoint,int maxTrailerSize,
+ Set<String> allowedTrailerHeaders, int maxExtensionSize, int maxSwallowSize) {
super(endpoint);
userDataHelper = new UserDataHelper(log);
@@ -255,8 +256,8 @@ public class Http11Processor extends Abs
outputBuffer.addFilter(new IdentityOutputFilter());
// Create and add the chunked filters.
- inputBuffer.addFilter(
- new ChunkedInputFilter(maxTrailerSize, maxExtensionSize, maxSwallowSize));
+ inputBuffer.addFilter(new ChunkedInputFilter(maxTrailerSize, allowedTrailerHeaders,
+ maxExtensionSize, maxSwallowSize));
outputBuffer.addFilter(new ChunkedOutputFilter());
// Create and add the void filters.
Modified: tomcat/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java?rev=1666386&r1=1666385&r2=1666386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/filters/BufferedInputFilter.java Fri Mar 13 10:02:34 2015
@@ -59,6 +59,8 @@ public class BufferedInputFilter impleme
/**
* Set the buffering limit. This should be reset every time the buffer is
* used.
+ *
+ * @param limit The maximum number of bytes that will be buffered
*/
public void setLimit(int limit) {
if (buffered == null) {
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=1666386&r1=1666385&r2=1666386&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java Fri Mar 13 10:02:34 2015
@@ -19,6 +19,8 @@ package org.apache.coyote.http11.filters
import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.Set;
import org.apache.coyote.InputBuffer;
import org.apache.coyote.Request;
@@ -146,10 +148,14 @@ public class ChunkedInputFilter implemen
private boolean error;
+ private final Set<String> allowedTrailerHeaders;
+
// ----------------------------------------------------------- Constructors
- public ChunkedInputFilter(int maxTrailerSize, int maxExtensionSize, int maxSwallowSize) {
+ public ChunkedInputFilter(int maxTrailerSize, Set<String> allowedTrailerHeaders,
+ int maxExtensionSize, int maxSwallowSize) {
this.trailingHeaders.setLimit(maxTrailerSize);
+ this.allowedTrailerHeaders = allowedTrailerHeaders;
this.maxExtensionSize = maxExtensionSize;
this.maxTrailerSize = maxTrailerSize;
this.maxSwallowSize = maxSwallowSize;
@@ -469,7 +475,7 @@ public class ChunkedInputFilter implemen
}
// Mark the current buffer position
- int start = trailingHeaders.getEnd();
+ int startPos = trailingHeaders.getEnd();
//
// Reading the header name
@@ -500,11 +506,7 @@ public class ChunkedInputFilter implemen
pos++;
}
- MessageBytes headerValue = headers.addValue(trailingHeaders.getBytes(),
- start, trailingHeaders.getEnd() - start);
-
- // Mark the current buffer position
- start = trailingHeaders.getEnd();
+ int colonPos = trailingHeaders.getEnd();
//
// Reading the header value (which can be spanned over multiple lines)
@@ -592,9 +594,16 @@ public class ChunkedInputFilter implemen
}
- // Set the header value
- headerValue.setBytes(trailingHeaders.getBytes(), start,
- lastSignificantChar - start);
+ String headerName = new String(trailingHeaders.getBytes(), startPos,
+ colonPos - startPos, StandardCharsets.ISO_8859_1);
+
+ if (allowedTrailerHeaders.contains(headerName.trim().toLowerCase(Locale.ENGLISH))) {
+ MessageBytes headerValue = headers.addValue(headerName);
+
+ // Set the header value
+ headerValue.setBytes(trailingHeaders.getBytes(), colonPos,
+ lastSignificantChar - colonPos);
+ }
return true;
}
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=1666386&r1=1666385&r2=1666386&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java Fri Mar 13 10:02:34 2015
@@ -104,6 +104,9 @@ public class TestChunkedInputFilter exte
// No file system docBase required
Context ctx = tomcat.addContext("", null);
+ // Configure allowed trailer headers
+ tomcat.getConnector().setProperty("allowedTrailerHeaders", "X-Trailer1,X-Trailer2");
+
EchoHeaderServlet servlet = new EchoHeaderServlet(expectPass);
Tomcat.addServlet(ctx, "servlet", servlet);
ctx.addServletMapping("/", "servlet");
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org