From dev-return-203875-archive-asf-public=cust-asf.ponee.io@tomcat.apache.org Thu Nov 28 14:44:58 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id E1D3A18064C for ; Thu, 28 Nov 2019 15:44:57 +0100 (CET) Received: (qmail 21649 invoked by uid 500); 28 Nov 2019 14:44:56 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 21639 invoked by uid 99); 28 Nov 2019 14:44:56 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Nov 2019 14:44:56 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 714F98B690; Thu, 28 Nov 2019 14:44:56 +0000 (UTC) Date: Thu, 28 Nov 2019 14:44:56 +0000 To: "dev@tomcat.apache.org" Subject: [tomcat] branch master updated: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63932 ETag & gzip MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <157495229634.3329.10867595498431859306@gitbox.apache.org> From: markt@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: tomcat X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 8995466c4ddec92d2263b4f2824561d7c1f4f69e X-Git-Newrev: 389231bccaa28d9a4142b91bfcdecec9d2fa9764 X-Git-Rev: 389231bccaa28d9a4142b91bfcdecec9d2fa9764 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/master by this push: new 389231b Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63932 ETag & gzip 389231b is described below commit 389231bccaa28d9a4142b91bfcdecec9d2fa9764 Author: Mark Thomas AuthorDate: Thu Nov 28 14:44:20 2019 +0000 Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63932 ETag & gzip By default, do not compress content that has a strong ETag. This behaviour is configuration for the HTTP/1.1 and HTTP/2 connectors via the new Connector attribute noCompressionStrongETag --- java/org/apache/coyote/CompressionConfig.java | 40 ++++++++++++++++++++++ .../coyote/http11/AbstractHttp11Protocol.java | 10 ++++++ java/org/apache/coyote/http2/Http2Protocol.java | 10 ++++++ test/org/apache/coyote/TestCompressionConfig.java | 33 ++++++++++++++---- webapps/docs/changelog.xml | 6 ++++ webapps/docs/config/http.xml | 8 +++++ webapps/docs/config/http2.xml | 8 +++++ 7 files changed, 108 insertions(+), 7 deletions(-) diff --git a/java/org/apache/coyote/CompressionConfig.java b/java/org/apache/coyote/CompressionConfig.java index 520ed2e..8bb11f9 100644 --- a/java/org/apache/coyote/CompressionConfig.java +++ b/java/org/apache/coyote/CompressionConfig.java @@ -46,6 +46,7 @@ public class CompressionConfig { "text/javascript,application/javascript,application/json,application/xml"; private String[] compressibleMimeTypes = null; private int compressionMinSize = 2048; + private boolean noCompressionStrongETag = true; /** @@ -183,6 +184,35 @@ public class CompressionConfig { /** + * Determine if compression is disabled if the resource has a strong ETag. + * + * @return {@code true} if compression is disabled, otherwise {@code false} + * + * @deprecated Will be removed in Tomcat 10 where it will be hard-coded to + * {@code true} + */ + @Deprecated + public boolean getNoCompressionStrongETag() { + return noCompressionStrongETag; + } + + + /** + * Set whether compression is disabled for resources with a strong ETag. + * + * @param noCompressionStrongETag {@code true} if compression is disabled, + * otherwise {@code false} + * + * @deprecated Will be removed in Tomcat 10 where it will be hard-coded to + * {@code true} + */ + @Deprecated + public void setNoCompressionStrongEtag(boolean noCompressionStrongETag) { + this.noCompressionStrongETag = noCompressionStrongETag; + } + + + /** * Determines if compression should be enabled for the given response and if * it is, sets any necessary headers to mark it as such. * @@ -235,6 +265,16 @@ public class CompressionConfig { } } + // Check if the resource has a strong ETag + if (noCompressionStrongETag) { + String eTag = responseHeaders.getHeader("ETag"); + if (eTag != null && !eTag.trim().startsWith("W/")) { + // Has an ETag that doesn't start with "W/..." so it must be a + // strong ETag + return false; + } + } + // If processing reaches this far, the response might be compressed. // Therefore, set the Vary header to keep proxies happy ResponseUtil.addVaryFieldName(responseHeaders, "accept-encoding"); diff --git a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java index 61d9a0c..70387b9 100644 --- a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java +++ b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java @@ -279,6 +279,16 @@ public abstract class AbstractHttp11Protocol extends AbstractProtocol { } + @Deprecated + public boolean getNoCompressionStrongETag() { + return compressionConfig.getNoCompressionStrongETag(); + } + @Deprecated + public void setNoCompressionStrongEtag(boolean noCompressionStrongETag) { + compressionConfig.setNoCompressionStrongEtag(noCompressionStrongETag); + } + + public boolean useCompression(Request request, Response response) { return compressionConfig.useCompression(request, response); } diff --git a/java/org/apache/coyote/http2/Http2Protocol.java b/java/org/apache/coyote/http2/Http2Protocol.java index 9597b79..1f3dfe0 100644 --- a/java/org/apache/coyote/http2/Http2Protocol.java +++ b/java/org/apache/coyote/http2/Http2Protocol.java @@ -405,6 +405,16 @@ public class Http2Protocol implements UpgradeProtocol { } + @Deprecated + public boolean getNoCompressionStrongETag() { + return compressionConfig.getNoCompressionStrongETag(); + } + @Deprecated + public void setNoCompressionStrongEtag(boolean noCompressionStrongETag) { + compressionConfig.setNoCompressionStrongEtag(noCompressionStrongETag); + } + + public boolean useCompression(Request request, Response response) { return compressionConfig.useCompression(request, response); } diff --git a/test/org/apache/coyote/TestCompressionConfig.java b/test/org/apache/coyote/TestCompressionConfig.java index 23d9d12..0d8c0a0 100644 --- a/test/org/apache/coyote/TestCompressionConfig.java +++ b/test/org/apache/coyote/TestCompressionConfig.java @@ -29,16 +29,24 @@ import org.junit.runners.Parameterized.Parameter; @RunWith(Parameterized.class) public class TestCompressionConfig { - @Parameterized.Parameters(name = "{index}: headers[{0}], compress[{1}]") + @Parameterized.Parameters(name = "{index}: accept-encoding[{0}], ETag [{1}], NoCompressionStrongETag[{2}], compress[{3}]") public static Collection parameters() { List parameterSets = new ArrayList<>(); - parameterSets.add(new Object[] { new String[] { }, Boolean.FALSE }); - parameterSets.add(new Object[] { new String[] { "gzip" }, Boolean.TRUE }); - parameterSets.add(new Object[] { new String[] { "xgzip" }, Boolean.FALSE }); - parameterSets.add(new Object[] { new String[] { "<>gzip" }, Boolean.FALSE }); - parameterSets.add(new Object[] { new String[] { "foo", "gzip" }, Boolean.TRUE }); - parameterSets.add(new Object[] { new String[] { "<>", "gzip" }, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { }, null, Boolean.TRUE, Boolean.FALSE }); + parameterSets.add(new Object[] { new String[] { "gzip" }, null, Boolean.TRUE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "xgzip" }, null, Boolean.TRUE, Boolean.FALSE }); + parameterSets.add(new Object[] { new String[] { "<>gzip" }, null, Boolean.TRUE, Boolean.FALSE }); + parameterSets.add(new Object[] { new String[] { "foo", "gzip" }, null, Boolean.TRUE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "<>", "gzip" }, null, Boolean.TRUE, Boolean.TRUE }); + + parameterSets.add(new Object[] { new String[] { "gzip" }, null, Boolean.TRUE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "gzip" }, "W/", Boolean.TRUE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "gzip" }, "XX", Boolean.TRUE, Boolean.FALSE }); + + parameterSets.add(new Object[] { new String[] { "gzip" }, null, Boolean.FALSE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "gzip" }, "W/", Boolean.FALSE, Boolean.TRUE }); + parameterSets.add(new Object[] { new String[] { "gzip" }, "XX", Boolean.FALSE, Boolean.TRUE }); return parameterSets; } @@ -46,14 +54,20 @@ public class TestCompressionConfig { @Parameter(0) public String[] headers; @Parameter(1) + public String eTag; + @Parameter(2) + public Boolean noCompressionStrongETag; + @Parameter(3) public Boolean compress; + @SuppressWarnings("deprecation") @Test public void testUseCompression() throws Exception { CompressionConfig compressionConfig = new CompressionConfig(); // Skip length and MIME type checks compressionConfig.setCompression("force"); + compressionConfig.setNoCompressionStrongEtag(noCompressionStrongETag.booleanValue()); Request request = new Request(); Response response = new Response(); @@ -62,6 +76,11 @@ public class TestCompressionConfig { request.getMimeHeaders().addValue("accept-encoding").setString(header); } + if (eTag != null) { + response.getMimeHeaders().addValue("ETag").setString(eTag); + } + + Assert.assertEquals(compress, Boolean.valueOf(compressionConfig.useCompression(request, response))); } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index c303810..3d46430 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -70,6 +70,12 @@ (remm) + 63932: By default, do not compress content that has a strong + ETag. This behaviour is configuration for the HTTP/1.1 and HTTP/2 + connectors via the new Connector attribute + noCompressionStrongETag. (markt) + + 63949: Fix non blocking write problems with NIO due to the need for a write loop. (remm) diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml index 0f95e65..057ee47 100644 --- a/webapps/docs/config/http.xml +++ b/webapps/docs/config/http.xml @@ -520,6 +520,14 @@ used.

+ +

This flag configures whether resources with a stong ETag will be + considered for compression. If true, resources with a strong + ETag will not be compressed. The default value is true.

+

This attribute is deprecated. It will be removed in Tomcat 10 onwards + where it will be hard-coded to true.

+
+

The value is a regular expression (using java.util.regex) matching the user-agent header of HTTP clients for which diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml index 02400e6..00f75cb 100644 --- a/webapps/docs/config/http2.xml +++ b/webapps/docs/config/http2.xml @@ -179,6 +179,14 @@ means no limit. If not specified, a default of 8192 is used.

+ +

This flag configures whether resources with a stong ETag will be + considered for compression. If true, resources with a strong + ETag will not be compressed. The default value is true.

+

This attribute is deprecated. It will be removed in Tomcat 10 onwards + where it will be hard-coded to true.

+
+

The value is a regular expression (using java.util.regex) matching the user-agent header of HTTP clients for which --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org