From bc4603925e351fbb987bbd06ec51afb033a25caf Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Sat, 22 Jul 2017 10:41:53 +0100 Subject: [PATCH] Configure Jetty to compress responses to requests other than GET Closes gh-8184 --- .../jetty/JettyServletWebServerFactory.java | 8 +++- .../JettyServletWebServerFactoryTests.java | 41 ------------------- .../AbstractServletWebServerFactoryTests.java | 36 +++++++++++++--- 3 files changed, 36 insertions(+), 49 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java index af02d9037f1..8cb8b062e7f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java @@ -32,6 +32,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.server.AbstractConnector; @@ -229,6 +230,9 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor Compression compression = getCompression(); handler.setMinGzipSize(compression.getMinResponseSize()); handler.setIncludedMimeTypes(compression.getMimeTypes()); + for (HttpMethod httpMethod : HttpMethod.values()) { + handler.addIncludedMethods(httpMethod.name()); + } if (compression.getExcludedUserAgents() != null) { handler.setExcludedAgentPatterns(compression.getExcludedUserAgents()); } @@ -581,8 +585,8 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor } /** - * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be applied - * to the {@link Server} before the it is created. + * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be + * applied to the {@link Server} before the it is created. * @return the {@link JettyServerCustomizer}s */ public Collection getServerCustomizers() { diff --git a/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java index f1d7af42a57..3b164ebb606 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java @@ -16,18 +16,12 @@ package org.springframework.boot.web.embedded.jetty; -import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.apache.jasper.servlet.JspServlet; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; @@ -43,13 +37,10 @@ import org.eclipse.jetty.webapp.WebAppContext; import org.junit.Test; import org.mockito.InOrder; -import org.springframework.boot.web.server.Compression; import org.springframework.boot.web.server.PortInUseException; import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory; import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; -import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.isA; @@ -296,38 +287,6 @@ public class JettyServletWebServerFactoryTests factory.getWebServer().start(); } - @Override - @SuppressWarnings("serial") - // Workaround for Jetty issue - https://bugs.eclipse.org/bugs/show_bug.cgi?id=470646 - protected String setUpFactoryForCompression(final int contentSize, String[] mimeTypes, - String[] excludedUserAgents) throws Exception { - char[] chars = new char[contentSize]; - Arrays.fill(chars, 'F'); - final String testContent = new String(chars); - AbstractServletWebServerFactory factory = getFactory(); - Compression compression = new Compression(); - compression.setEnabled(true); - if (mimeTypes != null) { - compression.setMimeTypes(mimeTypes); - } - if (excludedUserAgents != null) { - compression.setExcludedUserAgents(excludedUserAgents); - } - factory.setCompression(compression); - this.webServer = factory - .getWebServer(new ServletRegistrationBean(new HttpServlet() { - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - resp.setContentLength(contentSize); - resp.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain"); - resp.getWriter().print(testContent); - } - }, "/test.txt")); - this.webServer.start(); - return testContent; - } - @Override protected JspServlet getJspServlet() throws Exception { WebAppContext context = (WebAppContext) ((JettyWebServer) this.webServer) diff --git a/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index 5d712a4a590..0e06654aabd 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -58,7 +58,9 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.http.client.HttpClient; @@ -775,10 +777,15 @@ public abstract class AbstractServletWebServerFactoryTests { } @Test - public void compression() throws Exception { + public void compressionOfResposeToGetRequest() throws Exception { assertThat(doTestCompression(10000, null, null)).isTrue(); } + @Test + public void compressionOfResposeToPostRequest() throws Exception { + assertThat(doTestCompression(10000, null, null, HttpMethod.POST)).isTrue(); + } + @Test public void noCompressionForSmallResponse() throws Exception { assertThat(doTestCompression(100, null, null)).isFalse(); @@ -991,12 +998,18 @@ public abstract class AbstractServletWebServerFactoryTests { private boolean doTestCompression(int contentSize, String[] mimeTypes, String[] excludedUserAgents) throws Exception { + return doTestCompression(contentSize, mimeTypes, excludedUserAgents, + HttpMethod.GET); + } + + private boolean doTestCompression(int contentSize, String[] mimeTypes, + String[] excludedUserAgents, HttpMethod method) throws Exception { String testContent = setUpFactoryForCompression(contentSize, mimeTypes, excludedUserAgents); TestGzipInputStreamFactory inputStreamFactory = new TestGzipInputStreamFactory(); Map contentDecoderMap = Collections .singletonMap("gzip", (InputStreamFactory) inputStreamFactory); - String response = getResponse(getLocalUrl("/test.txt"), + String response = getResponse(getLocalUrl("/test.txt"), method, new HttpComponentsClientHttpRequestFactory( HttpClientBuilder.create().setUserAgent("testUserAgent") .setContentDecoderRegistry(contentDecoderMap).build())); @@ -1004,15 +1017,12 @@ public abstract class AbstractServletWebServerFactoryTests { return inputStreamFactory.wasCompressionUsed(); } - protected String setUpFactoryForCompression(int contentSize, String[] mimeTypes, + private String setUpFactoryForCompression(int contentSize, String[] mimeTypes, String[] excludedUserAgents) throws Exception { char[] chars = new char[contentSize]; Arrays.fill(chars, 'F'); String testContent = new String(chars); AbstractServletWebServerFactory factory = getFactory(); - FileCopyUtils.copy(testContent, - new FileWriter(this.temporaryFolder.newFile("test.txt"))); - factory.setDocumentRoot(this.temporaryFolder.getRoot()); Compression compression = new Compression(); compression.setEnabled(true); if (mimeTypes != null) { @@ -1022,6 +1032,20 @@ public abstract class AbstractServletWebServerFactoryTests { compression.setExcludedUserAgents(excludedUserAgents); } factory.setCompression(compression); + factory.addInitializers( + new ServletRegistrationBean(new HttpServlet() { + + @Override + protected void service(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + resp.setContentLength(testContent.length()); + resp.getWriter().write(testContent); + resp.getWriter().flush(); + } + + }, "/test.txt")); this.webServer = factory.getWebServer(); this.webServer.start(); return testContent;