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 2020/05/04 20:20:06 UTC
[tomcat] branch 8.5.x updated: Fix BZ 64403 Compressed h2 responses
should not have C-L header
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new 95b4827 Fix BZ 64403 Compressed h2 responses should not have C-L header
95b4827 is described below
commit 95b4827c9d59b01807d637b5dcadda26e4ff83fa
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon May 4 21:06:16 2020 +0100
Fix BZ 64403 Compressed h2 responses should not have C-L header
https://bz.apache.org/bugzilla/show_bug.cgi?id=64403
---
java/org/apache/coyote/http2/StreamProcessor.java | 16 +++--
.../apache/coyote/http2/TestStreamProcessor.java | 81 ++++++++++++++++++++++
webapps/docs/changelog.xml | 5 ++
3 files changed, 96 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java
index be6a353..6839b43 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -125,6 +125,16 @@ class StreamProcessor extends AbstractProcessor {
// Add the pseudo header for status
headers.addValue(":status").setString(Integer.toString(statusCode));
+
+ // Compression can't be used with sendfile
+ // Need to check for compression (and set headers appropriately) before
+ // adding headers below
+ if (protocol != null && protocol.useCompression(coyoteRequest, coyoteResponse)) {
+ // Enable compression. Headers will have been set. Need to configure
+ // output filter at this point.
+ stream.addOutputFilter(new GzipOutputFilter());
+ }
+
// Check to see if a response body is present
if (!(statusCode < 200 || statusCode == 204 || statusCode == 205 || statusCode == 304)) {
String contentType = coyoteResponse.getContentType();
@@ -156,12 +166,6 @@ class StreamProcessor extends AbstractProcessor {
if (statusCode >= 200 && headers.getValue("date") == null) {
headers.addValue("date").setString(FastHttpDateFormat.getCurrentDate());
}
-
- if (protocol != null && protocol.useCompression(coyoteRequest, coyoteResponse)) {
- // Enable compression. Headers will have been set. Need to configure
- // output filter at this point.
- stream.addOutputFilter(new GzipOutputFilter());
- }
}
diff --git a/test/org/apache/coyote/http2/TestStreamProcessor.java b/test/org/apache/coyote/http2/TestStreamProcessor.java
index a4dd5f1..a46e1b2 100644
--- a/test/org/apache/coyote/http2/TestStreamProcessor.java
+++ b/test/org/apache/coyote/http2/TestStreamProcessor.java
@@ -18,6 +18,7 @@ package org.apache.coyote.http2;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -34,6 +35,7 @@ import org.junit.Test;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
+import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.compat.JrePlatform;
import org.apache.tomcat.util.http.FastHttpDateFormat;
@@ -223,4 +225,83 @@ public class TestStreamProcessor extends Http2TestBase {
});
}
}
+
+
+ @Test
+ public void testCompression() throws Exception {
+ enableHttp2();
+
+ Tomcat tomcat = getTomcatInstance();
+
+ Context ctxt = tomcat.addContext("", null);
+ Tomcat.addServlet(ctxt, "simple", new SimpleServlet());
+ ctxt.addServletMappingDecoded("/simple", "simple");
+ Tomcat.addServlet(ctxt, "compression", new CompressionServlet());
+ ctxt.addServletMappingDecoded("/compression", "compression");
+
+ // Enable compression for the LargeServlet
+ Connector connector = tomcat.getConnector();
+ Assert.assertTrue(connector.setProperty("compression", "on"));
+
+ tomcat.start();
+
+ enableHttp2();
+ openClientConnection();
+ doHttpUpgrade();
+ sendClientPreface();
+ validateHttp2InitialResponse();
+
+
+ byte[] frameHeader = new byte[9];
+ ByteBuffer headersPayload = ByteBuffer.allocate(128);
+
+ List<Header> headers = new ArrayList<>(3);
+ headers.add(new Header(":method", "GET"));
+ headers.add(new Header(":scheme", "http"));
+ headers.add(new Header(":path", "/compression"));
+ headers.add(new Header(":authority", "localhost:" + getPort()));
+ headers.add(new Header("accept-encoding", "gzip"));
+
+ buildGetRequest(frameHeader, headersPayload, null, headers, 3);
+
+ writeFrame(frameHeader, headersPayload);
+
+ readSimpleGetResponse();
+
+ Assert.assertEquals(
+ "3-HeadersStart\n" +
+ "3-Header-[:status]-[200]\n" +
+ "3-Header-[vary]-[accept-encoding]\n" +
+ "3-Header-[content-encoding]-[gzip]\n" +
+ "3-Header-[content-type]-[text/plain;charset=UTF-8]\n" +
+ "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" +
+ "3-HeadersEnd\n" +
+ "3-Body-97\n" +
+ "3-EndOfStream\n", output.getTrace());
+ }
+
+
+ private static class CompressionServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Generate content type that is compressible
+ resp.setContentType("text/plain");
+ resp.setCharacterEncoding("UTF-8");
+
+ // Make ir large enough to trigger compression
+ int count = 64 * 1024;
+
+ // One bytes per entry
+ resp.setContentLengthLong(count);
+
+ OutputStream os = resp.getOutputStream();
+ for (int i = 0; i < count; i++) {
+ os.write('X');
+ }
+ }
+ }
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 0d4128d..c6446d3 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -115,6 +115,11 @@
keep-alive where the response has a non-2xx status code but the request
body has been fully read. (rjung/markt)
</fix>
+ <fix>
+ <bug>64403</bug>: Ensure that compressed HTTP/2 responses are not sent
+ with a content length header appropriate for the original, uncompressed
+ response. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org