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 @@
@@ -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 @@
@@ -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 @@
@@ -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