diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java index bb573ee04a9..b580148be21 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java @@ -16,6 +16,7 @@ package org.eclipse.jetty.servlet; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -170,7 +171,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc _resourceService.setAcceptRanges(getInitBoolean("acceptRanges", _resourceService.isAcceptRanges())); _resourceService.setDirAllowed(getInitBoolean("dirAllowed", _resourceService.isDirAllowed())); _resourceService.setRedirectWelcome(getInitBoolean("redirectWelcome", _resourceService.isRedirectWelcome())); - _resourceService.setPrecompressedFormats(parsePrecompressedFormats(getInitParameter("precompressed"), getInitBoolean("gzip", false))); + _resourceService.setPrecompressedFormats(parsePrecompressedFormats(getInitParameter("precompressed"), getInitBoolean("gzip"), _resourceService.getPrecompressedFormats())); _resourceService.setPathInfoOnly(getInitBoolean("pathInfoOnly", _resourceService.isPathInfoOnly())); _resourceService.setEtags(getInitBoolean("etags", _resourceService.isEtags())); @@ -303,8 +304,12 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc LOG.debug("resource base = {}", _resourceBase); } - private CompressedContentFormat[] parsePrecompressedFormats(String precompressed, boolean gzip) + private CompressedContentFormat[] parsePrecompressedFormats(String precompressed, Boolean gzip, CompressedContentFormat[] dft) { + if (precompressed == null && gzip == null) + { + return dft; + } List ret = new ArrayList<>(); if (precompressed != null && precompressed.indexOf('=') > 0) { @@ -314,7 +319,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc String encoding = setting[0].trim(); String extension = setting[1].trim(); ret.add(new CompressedContentFormat(encoding, extension)); - if (gzip && !ret.contains(CompressedContentFormat.GZIP)) + if (gzip == Boolean.TRUE && !ret.contains(CompressedContentFormat.GZIP)) ret.add(CompressedContentFormat.GZIP); } } @@ -326,7 +331,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc ret.add(CompressedContentFormat.GZIP); } } - else if (gzip) + else if (gzip == Boolean.TRUE) { // gzip handling is for backwards compatibility with older Jetty ret.add(CompressedContentFormat.GZIP); @@ -367,11 +372,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc return value; } - private boolean getInitBoolean(String name, boolean dft) + private Boolean getInitBoolean(String name) { String value = getInitParameter(name); if (value == null || value.length() == 0) - return dft; + return null; return (value.startsWith("t") || value.startsWith("T") || value.startsWith("y") || @@ -379,6 +384,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc value.startsWith("1")); } + private boolean getInitBoolean(String name, boolean dft) + { + return Optional.ofNullable(getInitBoolean(name)).orElse(dft); + } + private int getInitInt(String name, int dft) { String value = getInitParameter(name); diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java index 1acd1f5a524..1ec1f9d2c52 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java @@ -40,6 +40,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.CompressedContentFormat; import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpContent; import org.eclipse.jetty.http.HttpField; @@ -1968,6 +1969,51 @@ public class DefaultServletTest assertThat(body, containsString("fake gzip")); } + @Test + public void testProgrammaticCustomCompressionFormats() throws Exception + { + createFile(docRoot.resolve("data0.txt"), "Hello Text 0"); + createFile(docRoot.resolve("data0.txt.br"), "fake brotli"); + createFile(docRoot.resolve("data0.txt.gz"), "fake gzip"); + createFile(docRoot.resolve("data0.txt.bz2"), "fake bzip2"); + + ResourceService resourceService = new ResourceService(); + resourceService.setPrecompressedFormats(new CompressedContentFormat[]{ + new CompressedContentFormat("bzip2", ".bz2"), + new CompressedContentFormat("gzip", ".gz"), + new CompressedContentFormat("br", ".br") + }); + ServletHolder defholder = new ServletHolder(new DefaultServlet(resourceService)); + context.addServlet(defholder, "/"); + defholder.setInitParameter("resourceBase", docRoot.toString()); + + String rawResponse; + HttpTester.Response response; + String body; + + rawResponse = connector.getResponse("GET /context/data0.txt HTTP/1.0\r\nHost:localhost:8080\r\nAccept-Encoding:bzip2, br, gzip\r\n\r\n"); + response = HttpTester.parseResponse(rawResponse); + assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200)); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_LENGTH, "10")); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_TYPE, "text/plain")); + assertThat(response, containsHeaderValue(HttpHeader.VARY, "Accept-Encoding")); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_ENCODING, "bzip2")); + body = response.getContent(); + assertThat(body, containsString("fake bzip2")); + + // TODO: show accept-encoding search order issue (shouldn't this request return data0.txt.br?) + + rawResponse = connector.getResponse("GET /context/data0.txt HTTP/1.0\r\nHost:localhost:8080\r\nAccept-Encoding:br, gzip\r\n\r\n"); + response = HttpTester.parseResponse(rawResponse); + assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200)); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_LENGTH, "9")); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_TYPE, "text/plain")); + assertThat(response, containsHeaderValue(HttpHeader.VARY, "Accept-Encoding")); + assertThat(response, containsHeaderValue(HttpHeader.CONTENT_ENCODING, "gzip")); + body = response.getContent(); + assertThat(body, containsString("fake gzip")); + } + @Test public void testControlCharacter() throws Exception {