From 56ab0da2872de71fddf55ef035aedd5b04b99960 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 5 Jun 2018 17:18:45 +0200 Subject: [PATCH] Support EncodedResourceResolver in resource chain As of https://jira.spring.io/browse/SPR-16381, Spring Framework now supports both gzip and Brotli as compression formats for static resources resolved by the resource chain. The `GzipResourceResolver` has been deprecated and replaced by the `EncodedResourceResolver`. This commit uses this new resolver and adapts the configuration key to reflect those changes. Note that this resolver is now configured ahead of the `VersionResourceResolver`. Closes gh-13242 --- .../boot/autoconfigure/web/ResourceProperties.java | 14 +++++++------- .../web/reactive/WebFluxAutoConfiguration.java | 8 ++++---- .../web/servlet/WebMvcAutoConfiguration.java | 8 ++++---- .../additional-spring-configuration-metadata.json | 9 +++++++++ .../web/servlet/WebMvcAutoConfigurationTests.java | 10 +++++----- .../asciidoc/appendix-application-properties.adoc | 2 +- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java index 30f0aff919..491b1ffdc9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java @@ -112,10 +112,10 @@ public class ResourceProperties { private boolean htmlApplicationCache = false; /** - * Whether to enable resolution of already gzipped resources. Checks for a - * resource name variant with the "*.gz" extension. + * Whether to enable resolution of already compressed resources. Checks for a + * resource name with the '.gz' or '.br' file extensions. */ - private boolean gzipped = false; + private boolean compressed = false; private final Strategy strategy = new Strategy(); @@ -154,12 +154,12 @@ public class ResourceProperties { this.htmlApplicationCache = htmlApplicationCache; } - public boolean isGzipped() { - return this.gzipped; + public boolean isCompressed() { + return this.compressed; } - public void setGzipped(boolean gzipped) { - this.gzipped = gzipped; + public void setCompressed(boolean compressed) { + this.compressed = compressed; } static Boolean getEnabled(boolean fixedEnabled, boolean contentEnabled, diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index 351b08f79e..3033c98a92 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -64,7 +64,7 @@ import org.springframework.web.reactive.config.ViewResolverRegistry; import org.springframework.web.reactive.config.WebFluxConfigurationSupport; import org.springframework.web.reactive.config.WebFluxConfigurer; import org.springframework.web.reactive.resource.AppCacheManifestTransformer; -import org.springframework.web.reactive.resource.GzipResourceResolver; +import org.springframework.web.reactive.resource.EncodedResourceResolver; import org.springframework.web.reactive.resource.ResourceResolver; import org.springframework.web.reactive.resource.VersionResourceResolver; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; @@ -275,12 +275,12 @@ public class WebFluxAutoConfiguration { private void configureResourceChain(ResourceProperties.Chain properties, ResourceChainRegistration chain) { ResourceProperties.Strategy strategy = properties.getStrategy(); + if (properties.isCompressed()) { + chain.addResolver(new EncodedResourceResolver()); + } if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) { chain.addResolver(getVersionResourceResolver(strategy)); } - if (properties.isGzipped()) { - chain.addResolver(new GzipResourceResolver()); - } if (properties.isHtmlApplicationCache()) { chain.addTransformer(new AppCacheManifestTransformer()); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index 4299cd148a..e7672233ab 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -115,7 +115,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExc import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.resource.AppCacheManifestTransformer; -import org.springframework.web.servlet.resource.GzipResourceResolver; +import org.springframework.web.servlet.resource.EncodedResourceResolver; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.resource.ResourceResolver; import org.springframework.web.servlet.resource.VersionResourceResolver; @@ -602,12 +602,12 @@ public class WebMvcAutoConfiguration { private void configureResourceChain(ResourceProperties.Chain properties, ResourceChainRegistration chain) { Strategy strategy = properties.getStrategy(); + if (properties.isCompressed()) { + chain.addResolver(new EncodedResourceResolver()); + } if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) { chain.addResolver(getVersionResourceResolver(strategy)); } - if (properties.isGzipped()) { - chain.addResolver(new GzipResourceResolver()); - } if (properties.isHtmlApplicationCache()) { chain.addTransformer(new AppCacheManifestTransformer()); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index dafabc25de..b0f2e0fe1f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -455,6 +455,15 @@ "name": "spring.mvc.locale-resolver", "defaultValue": "accept-header" }, + { + "name" : "spring.resources.chain.gzipped", + "type" : "java.lang.Boolean", + "description" : "Whether to enable resolution of already gzipped resources. Checks for a resource name variant with the \"*.gz\" extension.", + "deprecation" : { + "replacement" : "spring.resources.chain.compressed", + "level" : "error" + } + }, { "name": "spring.quartz.jdbc.initialize-schema", "defaultValue": "embedded" diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java index d1e30f4fb0..986fedc20a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java @@ -90,8 +90,8 @@ import org.springframework.web.servlet.resource.CachingResourceResolver; import org.springframework.web.servlet.resource.CachingResourceTransformer; import org.springframework.web.servlet.resource.ContentVersionStrategy; import org.springframework.web.servlet.resource.CssLinkResourceTransformer; +import org.springframework.web.servlet.resource.EncodedResourceResolver; import org.springframework.web.servlet.resource.FixedVersionStrategy; -import org.springframework.web.servlet.resource.GzipResourceResolver; import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.resource.ResourceResolver; @@ -276,21 +276,21 @@ public class WebMvcAutoConfigurationTests { "spring.resources.chain.strategy.fixed.version:test", "spring.resources.chain.strategy.fixed.paths:/**/*.js", "spring.resources.chain.html-application-cache:true", - "spring.resources.chain.gzipped:true").run((context) -> { + "spring.resources.chain.compressed:true").run((context) -> { assertThat(getResourceResolvers(context, "/webjars/**")).hasSize(3); assertThat(getResourceTransformers(context, "/webjars/**")) .hasSize(2); assertThat(getResourceResolvers(context, "/**")) .extractingResultOf("getClass") - .containsOnly(VersionResourceResolver.class, - GzipResourceResolver.class, + .containsOnly(EncodedResourceResolver.class, + VersionResourceResolver.class, PathResourceResolver.class); assertThat(getResourceTransformers(context, "/**")) .extractingResultOf("getClass") .containsOnly(CssLinkResourceTransformer.class, AppCacheManifestTransformer.class); VersionResourceResolver resolver = (VersionResourceResolver) getResourceResolvers( - context, "/**").get(0); + context, "/**").get(1); Map strategyMap = resolver.getStrategyMap(); assertThat(strategyMap.get("/*.png")) .isInstanceOf(ContentVersionStrategy.class); diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index d01e0a6731..b44fee4a12 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -435,8 +435,8 @@ content into your application. Rather, pick only the properties that you need. spring.resources.cache.cachecontrol.stale-while-revalidate= # Maximum time the response can be served after it becomes stale, in seconds if no duration suffix is not specified. spring.resources.cache.period= # Cache period for the resources served by the resource handler. If a duration suffix is not specified, seconds will be used. spring.resources.chain.cache=true # Whether to enable caching in the Resource chain. + spring.resources.chain.compressed=false # Whether to enable resolution of already compressed resources (gzip, brotli). spring.resources.chain.enabled= # Whether to enable the Spring Resource Handling chain. By default, disabled unless at least one strategy has been enabled. - spring.resources.chain.gzipped=false # Whether to enable resolution of already gzipped resources. spring.resources.chain.html-application-cache=false # Whether to enable HTML5 application cache manifest rewriting. spring.resources.chain.strategy.content.enabled=false # Whether to enable the content Version Strategy. spring.resources.chain.strategy.content.paths=/** # Comma-separated list of patterns to apply to the content Version Strategy.