Configure Jetty to compress responses to requests other than GET
Closes gh-8184
This commit is contained in:
		
							parent
							
								
									6df1be3f1a
								
							
						
					
					
						commit
						bc4603925e
					
				|  | @ -32,6 +32,7 @@ import javax.servlet.ServletException; | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||||
| 
 | 
 | ||||||
|  | import org.eclipse.jetty.http.HttpMethod; | ||||||
| import org.eclipse.jetty.http.HttpVersion; | import org.eclipse.jetty.http.HttpVersion; | ||||||
| import org.eclipse.jetty.http.MimeTypes; | import org.eclipse.jetty.http.MimeTypes; | ||||||
| import org.eclipse.jetty.server.AbstractConnector; | import org.eclipse.jetty.server.AbstractConnector; | ||||||
|  | @ -229,6 +230,9 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor | ||||||
| 		Compression compression = getCompression(); | 		Compression compression = getCompression(); | ||||||
| 		handler.setMinGzipSize(compression.getMinResponseSize()); | 		handler.setMinGzipSize(compression.getMinResponseSize()); | ||||||
| 		handler.setIncludedMimeTypes(compression.getMimeTypes()); | 		handler.setIncludedMimeTypes(compression.getMimeTypes()); | ||||||
|  | 		for (HttpMethod httpMethod : HttpMethod.values()) { | ||||||
|  | 			handler.addIncludedMethods(httpMethod.name()); | ||||||
|  | 		} | ||||||
| 		if (compression.getExcludedUserAgents() != null) { | 		if (compression.getExcludedUserAgents() != null) { | ||||||
| 			handler.setExcludedAgentPatterns(compression.getExcludedUserAgents()); | 			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 | 	 * Returns a mutable collection of Jetty {@link JettyServerCustomizer}s that will be | ||||||
| 	 * to the {@link Server} before the it is created. | 	 * applied to the {@link Server} before the it is created. | ||||||
| 	 * @return the {@link JettyServerCustomizer}s | 	 * @return the {@link JettyServerCustomizer}s | ||||||
| 	 */ | 	 */ | ||||||
| 	public Collection<JettyServerCustomizer> getServerCustomizers() { | 	public Collection<JettyServerCustomizer> getServerCustomizers() { | ||||||
|  |  | ||||||
|  | @ -16,18 +16,12 @@ | ||||||
| 
 | 
 | ||||||
| package org.springframework.boot.web.embedded.jetty; | package org.springframework.boot.web.embedded.jetty; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; |  | ||||||
| import java.nio.charset.Charset; | import java.nio.charset.Charset; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.concurrent.TimeUnit; | 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.apache.jasper.servlet.JspServlet; | ||||||
| import org.eclipse.jetty.server.Handler; | import org.eclipse.jetty.server.Handler; | ||||||
| import org.eclipse.jetty.server.Server; | import org.eclipse.jetty.server.Server; | ||||||
|  | @ -43,13 +37,10 @@ import org.eclipse.jetty.webapp.WebAppContext; | ||||||
| import org.junit.Test; | import org.junit.Test; | ||||||
| import org.mockito.InOrder; | import org.mockito.InOrder; | ||||||
| 
 | 
 | ||||||
| import org.springframework.boot.web.server.Compression; |  | ||||||
| import org.springframework.boot.web.server.PortInUseException; | import org.springframework.boot.web.server.PortInUseException; | ||||||
| import org.springframework.boot.web.server.Ssl; | 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.AbstractServletWebServerFactory; | ||||||
| import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; | import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests; | ||||||
| import org.springframework.http.HttpHeaders; |  | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| import static org.hamcrest.CoreMatchers.isA; | import static org.hamcrest.CoreMatchers.isA; | ||||||
|  | @ -296,38 +287,6 @@ public class JettyServletWebServerFactoryTests | ||||||
| 		factory.getWebServer().start(); | 		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<HttpServlet>(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 | 	@Override | ||||||
| 	protected JspServlet getJspServlet() throws Exception { | 	protected JspServlet getJspServlet() throws Exception { | ||||||
| 		WebAppContext context = (WebAppContext) ((JettyWebServer) this.webServer) | 		WebAppContext context = (WebAppContext) ((JettyWebServer) this.webServer) | ||||||
|  |  | ||||||
|  | @ -58,7 +58,9 @@ import javax.servlet.ServletContext; | ||||||
| import javax.servlet.ServletException; | import javax.servlet.ServletException; | ||||||
| import javax.servlet.ServletRequest; | import javax.servlet.ServletRequest; | ||||||
| import javax.servlet.ServletResponse; | import javax.servlet.ServletResponse; | ||||||
|  | import javax.servlet.http.HttpServlet; | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
| import javax.servlet.http.HttpSession; | import javax.servlet.http.HttpSession; | ||||||
| 
 | 
 | ||||||
| import org.apache.http.client.HttpClient; | import org.apache.http.client.HttpClient; | ||||||
|  | @ -775,10 +777,15 @@ public abstract class AbstractServletWebServerFactoryTests { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	public void compression() throws Exception { | 	public void compressionOfResposeToGetRequest() throws Exception { | ||||||
| 		assertThat(doTestCompression(10000, null, null)).isTrue(); | 		assertThat(doTestCompression(10000, null, null)).isTrue(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void compressionOfResposeToPostRequest() throws Exception { | ||||||
|  | 		assertThat(doTestCompression(10000, null, null, HttpMethod.POST)).isTrue(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	public void noCompressionForSmallResponse() throws Exception { | 	public void noCompressionForSmallResponse() throws Exception { | ||||||
| 		assertThat(doTestCompression(100, null, null)).isFalse(); | 		assertThat(doTestCompression(100, null, null)).isFalse(); | ||||||
|  | @ -991,12 +998,18 @@ public abstract class AbstractServletWebServerFactoryTests { | ||||||
| 
 | 
 | ||||||
| 	private boolean doTestCompression(int contentSize, String[] mimeTypes, | 	private boolean doTestCompression(int contentSize, String[] mimeTypes, | ||||||
| 			String[] excludedUserAgents) throws Exception { | 			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, | 		String testContent = setUpFactoryForCompression(contentSize, mimeTypes, | ||||||
| 				excludedUserAgents); | 				excludedUserAgents); | ||||||
| 		TestGzipInputStreamFactory inputStreamFactory = new TestGzipInputStreamFactory(); | 		TestGzipInputStreamFactory inputStreamFactory = new TestGzipInputStreamFactory(); | ||||||
| 		Map<String, InputStreamFactory> contentDecoderMap = Collections | 		Map<String, InputStreamFactory> contentDecoderMap = Collections | ||||||
| 				.singletonMap("gzip", (InputStreamFactory) inputStreamFactory); | 				.singletonMap("gzip", (InputStreamFactory) inputStreamFactory); | ||||||
| 		String response = getResponse(getLocalUrl("/test.txt"), | 		String response = getResponse(getLocalUrl("/test.txt"), method, | ||||||
| 				new HttpComponentsClientHttpRequestFactory( | 				new HttpComponentsClientHttpRequestFactory( | ||||||
| 						HttpClientBuilder.create().setUserAgent("testUserAgent") | 						HttpClientBuilder.create().setUserAgent("testUserAgent") | ||||||
| 								.setContentDecoderRegistry(contentDecoderMap).build())); | 								.setContentDecoderRegistry(contentDecoderMap).build())); | ||||||
|  | @ -1004,15 +1017,12 @@ public abstract class AbstractServletWebServerFactoryTests { | ||||||
| 		return inputStreamFactory.wasCompressionUsed(); | 		return inputStreamFactory.wasCompressionUsed(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected String setUpFactoryForCompression(int contentSize, String[] mimeTypes, | 	private String setUpFactoryForCompression(int contentSize, String[] mimeTypes, | ||||||
| 			String[] excludedUserAgents) throws Exception { | 			String[] excludedUserAgents) throws Exception { | ||||||
| 		char[] chars = new char[contentSize]; | 		char[] chars = new char[contentSize]; | ||||||
| 		Arrays.fill(chars, 'F'); | 		Arrays.fill(chars, 'F'); | ||||||
| 		String testContent = new String(chars); | 		String testContent = new String(chars); | ||||||
| 		AbstractServletWebServerFactory factory = getFactory(); | 		AbstractServletWebServerFactory factory = getFactory(); | ||||||
| 		FileCopyUtils.copy(testContent, |  | ||||||
| 				new FileWriter(this.temporaryFolder.newFile("test.txt"))); |  | ||||||
| 		factory.setDocumentRoot(this.temporaryFolder.getRoot()); |  | ||||||
| 		Compression compression = new Compression(); | 		Compression compression = new Compression(); | ||||||
| 		compression.setEnabled(true); | 		compression.setEnabled(true); | ||||||
| 		if (mimeTypes != null) { | 		if (mimeTypes != null) { | ||||||
|  | @ -1022,6 +1032,20 @@ public abstract class AbstractServletWebServerFactoryTests { | ||||||
| 			compression.setExcludedUserAgents(excludedUserAgents); | 			compression.setExcludedUserAgents(excludedUserAgents); | ||||||
| 		} | 		} | ||||||
| 		factory.setCompression(compression); | 		factory.setCompression(compression); | ||||||
|  | 		factory.addInitializers( | ||||||
|  | 				new ServletRegistrationBean<HttpServlet>(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 = factory.getWebServer(); | ||||||
| 		this.webServer.start(); | 		this.webServer.start(); | ||||||
| 		return testContent; | 		return testContent; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue