From 699b6bc7e203ceb6bc9c9cb78cfd64f486c0c5f3 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 22 Oct 2024 09:05:58 -0500 Subject: [PATCH 1/2] Issue #12397 - Add more default excludes to GzipHandler. + Exclude more compressed mime-types + Exclude more compressed path extensions + Add missing compressed file types to mime.properties --- .../org/eclipse/jetty/http/mime.properties | 1 + .../src/main/java/module-info.java | 1 + .../server/handler/gzip/GzipHandler.java | 14 +++++ .../server/handler/gzip/GzipHandlerTest.java | 63 +++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties b/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties index d73e8b633279..ea9b8e5a1e10 100644 --- a/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties +++ b/jetty-core/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties @@ -200,3 +200,4 @@ xyz=chemical/x-xyz xz=application/x-xz z=application/compress zip=application/zip +zst=application/zstd diff --git a/jetty-core/jetty-server/src/main/java/module-info.java b/jetty-core/jetty-server/src/main/java/module-info.java index 8f3ef3e0f50a..7a9dd70a7b55 100644 --- a/jetty-core/jetty-server/src/main/java/module-info.java +++ b/jetty-core/jetty-server/src/main/java/module-info.java @@ -18,6 +18,7 @@ // Only required if using JMX. requires static org.eclipse.jetty.jmx; + requires java.desktop; exports org.eclipse.jetty.server; exports org.eclipse.jetty.server.handler; diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index 3ca1cbbc88e4..1cb08cd84610 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -85,13 +85,27 @@ else if (type.startsWith("image/") || type.startsWith("video/")) _mimeTypes.exclude(type); } + _mimeTypes.exclude("application/compress"); + _paths.exclude("*.z"); _mimeTypes.exclude("application/zip"); + _paths.exclude("*.zip"); + _mimeTypes.exclude("application/x-gtar"); + _paths.exclude("*.tgz"); + _mimeTypes.exclude("application/java-archive"); + _paths.exclude("*.jar"); _mimeTypes.exclude("application/gzip"); + _paths.exclude("*.gz", "*.gzip"); _mimeTypes.exclude("application/x-bzip2"); + _paths.exclude("*.bz2", "*.bzip", "*.bz"); _mimeTypes.exclude("application/brotli"); + _paths.exclude("*.br", "*.brotli"); _mimeTypes.exclude("application/x-xz"); + _paths.exclude("*.xz"); _mimeTypes.exclude("application/x-rar-compressed"); + _paths.exclude("*.rar"); + _mimeTypes.exclude("application/zstd"); + _paths.exclude("*.zst", "*.zstd"); // It is possible to use SSE with GzipHandler but you will need to set _synFlush to true which will impact performance. _mimeTypes.exclude("text/event-stream"); diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java index f30d72564c37..7d488c9c2d37 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/gzip/GzipHandlerTest.java @@ -81,6 +81,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; @@ -1750,6 +1751,68 @@ public void testSimpleCompressedResponse(int fileSize, WorkDir workDir) throws E assertThat("(Uncompressed) Content Hash", metadata.uncompressedSha1Sum, is(expectedSha1Sum)); } + /** + * Test of default GzipHandler configuration against requests to already compressed content-types. + * @param filename + */ + @ParameterizedTest + @CsvSource(delimiter = '|', textBlock = """ + # Filename | Content-Type + example.tar.gz | application/gzip + example.tgz | application/x-gtar + example.zip | application/zip + example.jar | application/java-archive + example.gz | application/gzip + example.bz2 | application/x-bzip2 + example.rar | application/x-rar-compressed + example.zst | application/zstd + """) + public void testDoNotRecompressDefault(String filename, String contentType, WorkDir workDir) throws Exception + { + Path tmpPath = workDir.getEmptyPathDir(); + Path contextDir = tmpPath.resolve("context"); + FS.ensureDirExists(contextDir); + + _contextHandler.setBaseResourceAsPath(contextDir); + ResourceHandler resourceHandler = new ResourceHandler(); + resourceHandler.setEtags(true); + _contextHandler.setHandler(resourceHandler); + + int filesize = 2048; + + // Prepare Server File + Path file = Files.write(contextDir.resolve(filename), generateContent(filesize)); + String expectedSha1Sum = Sha1Sum.calculate(file); + + _server.start(); + + // Setup request + HttpTester.Request request = HttpTester.newRequest(); + request.setMethod("GET"); + request.setVersion(HttpVersion.HTTP_1_1); + request.setHeader("Host", "tester"); + request.setHeader("Connection", "close"); + request.setHeader("Accept-Encoding", "gzip"); + request.setURI("/ctx/" + filename); + + // Issue request + ByteBuffer rawResponse = _connector.getResponse(request.generate(), 5, TimeUnit.SECONDS); + + // Parse response + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + assertThat("Response status", response.getStatus(), is(HttpStatus.OK_200)); + + // Response Content-Encoding check + assertThat("Response[Content-Encoding]", response.get("Content-Encoding"), nullValue()); + assertThat("Response[Vary]", response.get("Vary"), nullValue()); + + // Response Content checks + UncompressedMetadata metadata = parseResponseContent(response); + assertThat("(Uncompressed) Content Length", metadata.uncompressedSize, is(filesize)); + assertThat("(Uncompressed) Content Hash", metadata.uncompressedSha1Sum, is(expectedSha1Sum)); + } + protected FilterInputStream newContentEncodingFilterInputStream(String contentEncoding, InputStream inputStream) throws IOException { if (contentEncoding == null) From d2c78d7afdc4774897a914aac4feeabf87f88074 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 22 Oct 2024 09:38:21 -0500 Subject: [PATCH 2/2] Revert change to module-info.java --- jetty-core/jetty-server/src/main/java/module-info.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jetty-core/jetty-server/src/main/java/module-info.java b/jetty-core/jetty-server/src/main/java/module-info.java index 7a9dd70a7b55..8f3ef3e0f50a 100644 --- a/jetty-core/jetty-server/src/main/java/module-info.java +++ b/jetty-core/jetty-server/src/main/java/module-info.java @@ -18,7 +18,6 @@ // Only required if using JMX. requires static org.eclipse.jetty.jmx; - requires java.desktop; exports org.eclipse.jetty.server; exports org.eclipse.jetty.server.handler;