Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63824
Correctly parse the Connection header when checking to see if the
"close" option is present.
diff --git a/java/org/apache/coyote/http11/Http11Processor.java b/java/org/apache/coyote/http11/Http11Processor.java
index a176206..80d427f 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -18,9 +18,12 @@
import java.io.IOException;
import java.io.InterruptedIOException;
+import java.io.StringReader;
import java.nio.ByteBuffer;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Locale;
+import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
@@ -52,6 +55,7 @@
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.parser.HttpParser;
+import org.apache.tomcat.util.http.parser.TokenList;
import org.apache.tomcat.util.log.UserDataHelper;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.SSLSupport;
@@ -900,7 +904,7 @@
}
long contentLength = response.getContentLengthLong();
- boolean connectionClosePresent = false;
+ boolean connectionClosePresent = isConnectionClose(headers);
if (http11 && response.getTrailerFields() != null) {
// If trailer fields are set, always use chunking
outputBuffer.addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
@@ -913,7 +917,6 @@
} else {
// If the response code supports an entity body and we're on
// HTTP 1.1 then we chunk unless we have a Connection: close header
- connectionClosePresent = isConnectionClose(headers);
if (http11 && entityBody && !connectionClosePresent) {
outputBuffer.addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
contentDelimitation = true;
@@ -992,12 +995,25 @@
outputBuffer.commit();
}
- private static boolean isConnectionClose(MimeHeaders headers) {
+ private static boolean isConnectionClose(MimeHeaders headers) throws IOException {
MessageBytes connection = headers.getValue(Constants.CONNECTION);
if (connection == null) {
return false;
}
- return connection.equals(Constants.CLOSE);
+
+ Enumeration<String> values = headers.values(Constants.CONNECTION);
+ Set<String> result = null;
+ while (values.hasMoreElements()) {
+ if (result == null) {
+ result = new HashSet<>();
+ }
+ TokenList.parseTokenList(new StringReader(values.nextElement()), result);
+ }
+
+ if (result == null) {
+ return false;
+ }
+ return result.contains(Constants.CLOSE);
}
private void prepareSendfile(OutputFilter[] outputFilters) {