diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml index d64d4ae0ce..cc9eee48c4 100644 --- a/spring-boot-autoconfigure/pom.xml +++ b/spring-boot-autoconfigure/pom.xml @@ -160,6 +160,11 @@ HikariCP-java6 true + + org.eclipse.jetty + jetty-servlets + true + org.eclipse.jetty jetty-webapp diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfiguration.java new file mode 100644 index 0000000000..eb12a29860 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web; + +import org.eclipse.jetty.servlets.GzipFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for {@link GzipFilter}. + * + * @author Andy Wilkinson + * @since 1.2.2 + */ +@Configuration +@ConditionalOnClass(GzipFilter.class) +@EnableConfigurationProperties(GzipFilterProperties.class) +public class GzipFilterAutoConfiguration { + + @Autowired + private GzipFilterProperties properties; + + @Bean + public FilterRegistrationBean gzipFilter() { + FilterRegistrationBean registration = new FilterRegistrationBean(new GzipFilter()); + registration.addUrlPatterns("/*"); + registration.setInitParameters(this.properties.getAsInitParameters()); + + return registration; + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterProperties.java new file mode 100644 index 0000000000..473912d6cb --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/GzipFilterProperties.java @@ -0,0 +1,226 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jetty.servlets.GzipFilter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.http.HttpMethod; +import org.springframework.util.MimeType; +import org.springframework.util.StringUtils; + +/** + * Properties for configuring {@link GzipFilter}. + * + * @author Andy Wilkinson + * @since 1.2.2 + */ +@ConfigurationProperties(prefix = "spring.http.gzip") +public class GzipFilterProperties { + + private final Map initParameters = new HashMap(); + + /** + * Size of the output buffer in bytes. + */ + private Integer bufferSize; + + /** + * Minimum content length required for compression to occur. + */ + private Integer minGzipSize; + + /** + * The level used for deflate compression (0-9). + */ + private Integer deflateCompressionLevel; + + /** + * noWrap setting for deflate compression. + */ + private Boolean deflateNoWrap; + + /** + * Comma-separated list of HTTP methods for which compression is enabled. + */ + private List methods; + + /** + * Comma-separated list of MIME types which should be compressed. + */ + private List mimeTypes; + + /** + * Comma-separated list of user agents to exclude from compression. String.contains is + * used to determine a match against the request's User-Agent header. + */ + private String excludedAgents; + + /** + * Comma-separated list of regular expression patterns to control user agents excluded + * from compression. + */ + private String excludedAgentPatterns; + + /** + * Comma-separated list of paths to exclude from compression. Uses String.startsWith + * to determine a match against the request's path. + */ + private String excludedPaths; + + /** + * Comma-separated list of regular expression patterns to control the paths that are + * excluded from compression. + */ + private String excludedPathPatterns; + + /** + * Vary header sent on responses that may be compressed. + */ + private String vary; + + public GzipFilterProperties() { + this.addInitParameter("checkGzExists", false); + } + + public Integer getBufferSize() { + return this.bufferSize; + } + + public void setBufferSize(Integer bufferSize) { + this.addInitParameter("bufferSize", bufferSize); + this.bufferSize = bufferSize; + } + + public Integer getMinGzipSize() { + return this.minGzipSize; + } + + public void setMinGzipSize(Integer minGzipSize) { + this.addInitParameter("minGzipSize", minGzipSize); + this.minGzipSize = minGzipSize; + } + + public Integer getDeflateCompressionLevel() { + return this.deflateCompressionLevel; + } + + public void setDeflateCompressionLevel(Integer deflateCompressionLevel) { + this.addInitParameter("deflateCompressionLevel", deflateCompressionLevel); + this.deflateCompressionLevel = deflateCompressionLevel; + } + + public Boolean getDeflateNoWrap() { + return this.deflateNoWrap; + } + + public void setDeflateNoWrap(Boolean deflateNoWrap) { + this.addInitParameter("deflateNoWrap", deflateNoWrap); + this.deflateNoWrap = deflateNoWrap; + } + + public List getMethods() { + return this.methods; + } + + public void setMethods(List methods) { + this.addInitParameter("methods", + StringUtils.collectionToCommaDelimitedString(methods)); + this.methods = methods; + } + + public List getMimeTypes() { + return this.mimeTypes; + } + + public void setMimeTypes(List mimeTypes) { + this.addInitParameter("mimeTypes", + StringUtils.collectionToCommaDelimitedString(mimeTypes)); + this.mimeTypes = mimeTypes; + } + + public String getExcludedAgents() { + return this.excludedAgents; + } + + public void setExcludedAgents(String excludedAgents) { + this.addInitParameter("excludedAgents", excludedAgents); + this.excludedAgents = excludedAgents; + } + + public String getExcludedAgentPatterns() { + return this.excludedAgentPatterns; + } + + public void setExcludedAgentPatterns(String excludedAgentPatterns) { + this.addInitParameter("excludedAgentPatterns", excludedAgentPatterns); + this.excludedAgentPatterns = excludedAgentPatterns; + } + + public String getExcludedPaths() { + return this.excludedPaths; + } + + public void setExcludedPaths(String excludedPaths) { + this.addInitParameter("excludedPaths", excludedPaths); + this.excludedPaths = excludedPaths; + } + + public String getExcludedPathPatterns() { + return this.excludedPathPatterns; + } + + public void setExcludedPathPatterns(String excludedPathPatterns) { + this.addInitParameter("excludedPathPatterns", excludedPathPatterns); + this.excludedPathPatterns = excludedPathPatterns; + } + + public String getVary() { + return this.vary; + } + + public void setVary(String vary) { + this.addInitParameter("vary", vary); + this.vary = vary; + } + + Map getAsInitParameters() { + return this.initParameters; + } + + private void addInitParameter(String name, Integer value) { + if (value != null) { + this.initParameters.put(name, value.toString()); + } + } + + private void addInitParameter(String name, Boolean value) { + if (value != null) { + this.initParameters.put(name, value.toString()); + } + } + + private void addInitParameter(String name, String value) { + if (value != null) { + this.initParameters.put(name, value.toString()); + } + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index 69a50539ab..6565b7f76c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -307,6 +307,19 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord */ private String uriEncoding; + /** + * Controls response compression. Acceptable values are "off" to disable + * compression, "on" to enable compression of responses over 2048 bytes, "force" + * to force response compression, or an integer value to enable compression of + * responses with content length that is at least that value. + */ + private String compression = "off"; + + /** + * A comma-separated list of MIME types for which compression is used. + */ + private String compressableMimeTypes = "text/html,text/xml,text/plain"; + public int getMaxThreads() { return this.maxThreads; } @@ -355,6 +368,22 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord this.accessLogPattern = accessLogPattern; } + public String getCompressableMimeTypes() { + return this.compressableMimeTypes; + } + + public void setCompressableMimeTypes(String compressableMimeTypes) { + this.compressableMimeTypes = compressableMimeTypes; + } + + public String getCompression() { + return this.compression; + } + + public void setCompression(String compression) { + this.compression = compression; + } + public String getInternalProxies() { return this.internalProxies; } @@ -447,6 +476,19 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord }); } + factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { + @Override + public void customize(Connector connector) { + ProtocolHandler handler = connector.getProtocolHandler(); + if (handler instanceof AbstractHttp11Protocol) { + @SuppressWarnings("rawtypes") + AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) handler; + protocol.setCompression(Tomcat.this.compression); + protocol.setCompressableMimeTypes(Tomcat.this.compressableMimeTypes); + } + } + }); + if (this.accessLogEnabled) { AccessLogValve valve = new AccessLogValve(); String accessLogPattern = getAccessLogPattern(); diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 1db59da3c7..f3f3ca601e 100644 --- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -57,14 +57,15 @@ org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ -org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\ -org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ -org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.GzipFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\ -org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration # Template availability providers diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfigurationTests.java new file mode 100644 index 0000000000..ec6d0e928d --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/GzipFilterAutoConfigurationTests.java @@ -0,0 +1,112 @@ +/* + * Copyright 2012-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web; + +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.context.embedded.FilterRegistrationBean; +import org.springframework.boot.test.EnvironmentTestUtils; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link GzipFilterAutoConfiguration} + * + * @author Andy Wilkinson + */ +public class GzipFilterAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void filterIsMappedToSlashStar() { + createAndRefreshContext(); + FilterRegistrationBean registrationBean = this.context.getBean("gzipFilter", + FilterRegistrationBean.class); + assertThat(registrationBean.getUrlPatterns(), contains("/*")); + } + + @Test + public void byDefaultCheckGzExistsIsTheOnlyInitParameter() { + createAndRefreshContext(); + FilterRegistrationBean registrationBean = this.context.getBean("gzipFilter", + FilterRegistrationBean.class); + assertThat(registrationBean.getInitParameters().size(), equalTo(1)); + assertThat(registrationBean.getInitParameters().get("checkGzExists"), + equalTo("false")); + } + + @Test + public void customInitParameterConfiguration() { + createAndRefreshContext("spring.http.gzip.bufferSize:1234", + "spring.http.gzip.minGzipSize:2345", + "spring.http.gzip.deflateCompressionLevel:5", + "spring.http.gzip.deflateNoWrap:false", + "spring.http.gzip.methods:GET,POST", + "spring.http.gzip.mimeTypes:application/foo,application/bar", + "spring.http.gzip.excludedAgents:excluded-agent-1,excluded-agent-2", + "spring.http.gzip.excludedAgentPatterns:agent-pattern-1,agent-pattern-2", + "spring.http.gzip.excludedPaths:/static/", + "spring.http.gzip.excludedPathPatterns:path-pattern", + "spring.http.gzip.vary:vary-header-value"); + FilterRegistrationBean registrationBean = this.context.getBean("gzipFilter", + FilterRegistrationBean.class); + assertThat(registrationBean.getInitParameters().size(), equalTo(12)); + assertThat(registrationBean.getInitParameters().get("checkGzExists"), + equalTo("false")); + assertThat(registrationBean.getInitParameters().get("bufferSize"), + equalTo("1234")); + assertThat(registrationBean.getInitParameters().get("minGzipSize"), + equalTo("2345")); + assertThat(registrationBean.getInitParameters().get("deflateCompressionLevel"), + equalTo("5")); + assertThat(registrationBean.getInitParameters().get("deflateNoWrap"), + equalTo("false")); + assertThat(registrationBean.getInitParameters().get("methods"), + equalTo("GET,POST")); + assertThat(registrationBean.getInitParameters().get("mimeTypes"), + equalTo("application/foo,application/bar")); + assertThat(registrationBean.getInitParameters().get("excludedAgents"), + equalTo("excluded-agent-1,excluded-agent-2")); + assertThat(registrationBean.getInitParameters().get("excludedAgentPatterns"), + equalTo("agent-pattern-1,agent-pattern-2")); + assertThat(registrationBean.getInitParameters().get("excludedPaths"), + equalTo("/static/")); + assertThat(registrationBean.getInitParameters().get("excludedPathPatterns"), + equalTo("path-pattern")); + assertThat(registrationBean.getInitParameters().get("vary"), + equalTo("vary-header-value")); + } + + private void createAndRefreshContext(String... pairs) { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, pairs); + this.context.register(GzipFilterAutoConfiguration.class); + this.context.refresh(); + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 66f75e8604..bd2a13d065 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,12 @@ import java.util.Map; import org.apache.catalina.Valve; import org.apache.catalina.valves.RemoteIpValve; +import org.apache.coyote.http11.AbstractHttp11Protocol; import org.junit.Test; import org.springframework.beans.MutablePropertyValues; import org.springframework.boot.bind.RelaxedDataBinder; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import static org.hamcrest.core.IsInstanceOf.instanceOf; @@ -193,6 +195,52 @@ public class ServerPropertiesTests { assertEquals("192.168.0.1", remoteIpValve.getInternalProxies()); } + @Test + public void customTomcatCompression() throws Exception { + Map map = new HashMap(); + map.put("server.port", "0"); + map.put("server.tomcat.compression", "on"); + bindProperties(map); + + TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); + this.properties.customize(factory); + + TomcatEmbeddedServletContainer container = (TomcatEmbeddedServletContainer) factory + .getEmbeddedServletContainer(); + + try { + AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) container + .getTomcat().getConnector().getProtocolHandler(); + assertEquals("on", protocol.getCompression()); + } + finally { + container.stop(); + } + } + + @Test + public void customTomcatCompressableMimeTypes() throws Exception { + Map map = new HashMap(); + map.put("server.port", "0"); + map.put("server.tomcat.compressableMimeTypes", "application/foo"); + bindProperties(map); + + TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); + this.properties.customize(factory); + + TomcatEmbeddedServletContainer container = (TomcatEmbeddedServletContainer) factory + .getEmbeddedServletContainer(); + + try { + AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) container + .getTomcat().getConnector().getProtocolHandler(); + assertEquals("application/foo", protocol.getCompressableMimeTypes()); + } + finally { + container.stop(); + } + } + private void bindProperties(Map map) { new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues( map)); diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index 8699ee2fff..2b42cc79c8 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -983,6 +983,11 @@ jetty-security ${jetty.version} + + org.eclipse.jetty + jetty-server + ${jetty.version} + org.eclipse.jetty jetty-servlet @@ -990,7 +995,7 @@ org.eclipse.jetty - jetty-server + jetty-servlets ${jetty.version} diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 4f3ed3db10..976d9ac0a2 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -74,6 +74,8 @@ content into your application; rather pick only the properties that you need. server.ssl.trust-store-type= server.tomcat.access-log-pattern= # log pattern of the access log server.tomcat.access-log-enabled=false # is access logging enabled + server.tomcat.compression=off # is compression enabled (off, on, or an integer content length limit) + server.tomcat.compressableMimeTypes=text/html,text/xml,text/plain # comma-separated list of mime types that Tomcat will compress server.tomcat.internal-proxies=10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\ 192\\.168\\.\\d{1,3}\\.\\d{1,3}|\\ 169\\.254\\.\\d{1,3}\\.\\d{1,3}|\\ @@ -105,6 +107,19 @@ content into your application; rather pick only the properties that you need. spring.http.encoding.enabled=true # enable http encoding support spring.http.encoding.force=true # force the configured encoding + # HTTP response compression ({sc-spring-boot-autoconfigure/web/GzipFilterProperties.{sc-ext}[GzipFilterProperties]) + spring.http.gzip.bufferSize= # size of the output buffer in bytes + spring.http.gzip.minGzipSize= # minimum content length required for compression to occur + spring.http.gzip.deflateCompressionLevel= # the level used for deflate compression (0-9) + spring.http.gzip.deflateNoWrap= # noWrap setting for deflate compression (true or false) + spring.http.gzip.methods= # comma-separated list of HTTP methods for which compression is enabled + spring.http.gzip.mimeTypes= # comma-separated list of MIME types which should be compressed + spring.http.gzip.excludedAgents= # comma-separated list of user agents to exclude from compression + spring.http.gzip.excludedAgentPatterns= # comma-separated list of regular expression patterns to control user agents excluded from compression + spring.http.gzip.excludedPaths= # comma-separated list of paths to exclude from compression + spring.http.gzip.excludedPathPatterns= # comma-separated list of regular expression patterns to control the paths that are excluded from compression + spring.http.gzip.vary= # Vary header to be sent on responses that may be compressed + # JACKSON ({sc-spring-boot-autoconfigure}}/jackson/JacksonProperties.{sc-ext}[JacksonProperties]) spring.jackson.date-format= # Date format string (e.g. yyyy-MM-dd HH:mm:ss), or a fully-qualified date format class name (e.g. com.fasterxml.jackson.databind.util.ISO8601DateFormat) spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy (e.g. CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES) or the fully-qualified class name of a PropertyNamingStrategy subclass diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 21cdcb8141..6ee4bf6b06 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -740,6 +740,58 @@ not required. +[[how-to-enable-http-response-compression]] +=== Enable HTTP response compression +Spring Boot provides two mechanisms for enabling compression of HTTP compression; one +that is Tomcat-specific and another that uses a filter and works with Jetty, Tomcat, +and Undertow. + + + +[[how-to-enable-http-response-compression-tomcat]] +==== Enable Tomcat's HTTP response compression +Tomcat provides built-in support for HTTP response compression. It is disabled by +default, but can easily be enabled via `application.properties`: + +[source,properties,indent=0,subs="verbatim,quotes,attributes"] +---- + server.tomcat.compression: on +---- + +When set to `on` Tomcat will compress responses with a length that is at least 2048 +bytes. This limit can be configured by specifying an integer value rather than `on`, +e.g.: + +[source,properties,indent=0,subs="verbatim,quotes,attributes"] +---- + server.tomcat.compression: 4096 +---- + +By default Tomcat will only compress responses with certain MIME types +(`text/html`, `text/xml`, and `text/plain`). You can customize this using the +`server.tomcat.compressableMimeTypes` property, e.g.: + +[source,properties,indent=0,subs="verbatim,quotes,attributes"] +---- + server.tomcat.compressableMimeTypes=application/json,application/xml +---- + + + +[[how-to-enable-http-compression-gzip-filter]] +==== Enable HTTP response compression using GzipFilter +If you're using Jetty or Undertow, or you want more sophisticated control over +HTTP response compression, Spring Boot provides auto-configuration for Jetty's +`GzipFilter`. While this filter is part of Jetty, it's compatible with Tomcat +and Undertow as well. To enable the filter, simply add a dependency on +`org.eclipse.jetty:jetty-servlets` to your application. + +`GzipFilter` can be configured using the `spring.http.gzip.*` properties. See +{sc-spring-boot-autoconfigure}/web/GzipFilterProperties.{sc-ext}[`GzipFilterProperties`] +for more details. + + + [[howto-spring-mvc]] == Spring MVC