Browse Source
Jetty’s GzipFilter is a container-agnostic Filter that can be used to provide gzip and deflate encoding of HTTP responses. This commit adds auto-configuration for GzipFilter that is enabled when org.eclipse.jetty:jetty-servlets is on the classpath. The filter can be configured using spring.http.gzip.* See gh-2031pull/2370/merge
6 changed files with 405 additions and 5 deletions
@ -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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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<String, String> initParameters = new HashMap<String, String>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 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<HttpMethod> methods; |
||||||
|
|
||||||
|
/** |
||||||
|
* Comma-separated list of MIME types which should be compressed. |
||||||
|
*/ |
||||||
|
private List<MimeType> 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<HttpMethod> getMethods() { |
||||||
|
return this.methods; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMethods(List<HttpMethod> methods) { |
||||||
|
this.addInitParameter("methods", |
||||||
|
StringUtils.collectionToCommaDelimitedString(methods)); |
||||||
|
this.methods = methods; |
||||||
|
} |
||||||
|
|
||||||
|
public List<MimeType> getMimeTypes() { |
||||||
|
return this.mimeTypes; |
||||||
|
} |
||||||
|
|
||||||
|
public void setMimeTypes(List<MimeType> 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<String, String> 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()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -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(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue