Commit e01c92a3 authored by Phillip Webb's avatar Phillip Webb

Polish

parent 64c5e8b6
...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web; ...@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.web;
import java.time.Duration; import java.time.Duration;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.convert.DefaultDurationUnit; import org.springframework.boot.context.properties.bind.convert.DefaultDurationUnit;
...@@ -48,16 +49,16 @@ public class ResourceProperties { ...@@ -48,16 +49,16 @@ public class ResourceProperties {
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS; private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
/** /**
* Cache period for the resources served by the resource handler. * Cache period for the resources served by the resource handler. If a duration suffix
* If a duration suffix is not specified, seconds will be used. * is not specified, seconds will be used. Can be overridden by the 'cache-control'
* Can be overridden by the {@code cache-control} property. * property.
*/ */
@DefaultDurationUnit(ChronoUnit.SECONDS) @DefaultDurationUnit(ChronoUnit.SECONDS)
private Duration cachePeriod; private Duration cachePeriod;
/** /**
* Cache control HTTP headers, only allows valid directive combinations. * Cache control HTTP headers, only allows valid directive combinations. Overrides the
* Overrides the {@code cache-period} property. * 'cache-period' property.
*/ */
private CacheControlProperties cacheControl = new CacheControlProperties(); private CacheControlProperties cacheControl = new CacheControlProperties();
...@@ -145,9 +146,8 @@ public class ResourceProperties { ...@@ -145,9 +146,8 @@ public class ResourceProperties {
/** /**
* Return whether the resource chain is enabled. Return {@code null} if no * Return whether the resource chain is enabled. Return {@code null} if no
* specific settings are present. * specific settings are present.
* * @return whether the resource chain is enabled or {@code null} if no specified
* @return whether the resource chain is enabled or {@code null} if no specified settings are * settings are present.
* present.
*/ */
public Boolean getEnabled() { public Boolean getEnabled() {
return getEnabled(getStrategy().getFixed().isEnabled(), return getEnabled(getStrategy().getFixed().isEnabled(),
...@@ -225,7 +225,7 @@ public class ResourceProperties { ...@@ -225,7 +225,7 @@ public class ResourceProperties {
/** /**
* Comma-separated list of patterns to apply to the Version Strategy. * Comma-separated list of patterns to apply to the Version Strategy.
*/ */
private String[] paths = new String[]{"/**"}; private String[] paths = new String[] { "/**" };
public boolean isEnabled() { public boolean isEnabled() {
return this.enabled; return this.enabled;
...@@ -258,7 +258,7 @@ public class ResourceProperties { ...@@ -258,7 +258,7 @@ public class ResourceProperties {
/** /**
* Comma-separated list of patterns to apply to the Version Strategy. * Comma-separated list of patterns to apply to the Version Strategy.
*/ */
private String[] paths = new String[]{"/**"}; private String[] paths = new String[] { "/**" };
/** /**
* Version string to use for the Version Strategy. * Version string to use for the Version Strategy.
...@@ -297,15 +297,15 @@ public class ResourceProperties { ...@@ -297,15 +297,15 @@ public class ResourceProperties {
public static class CacheControlProperties { public static class CacheControlProperties {
/** /**
* Maximum time the response should be cached, * Maximum time the response should be cached, in seconds if no duration suffix is
* in seconds if no duration suffix is not specified. * not specified.
*/ */
@DefaultDurationUnit(ChronoUnit.SECONDS) @DefaultDurationUnit(ChronoUnit.SECONDS)
private Duration maxAge; private Duration maxAge;
/** /**
* Indicate that the cached response can be reused only * Indicate that the cached response can be reused only if re-validated with the
* if re-validated with the server. * server.
*/ */
private Boolean noCache; private Boolean noCache;
...@@ -315,14 +315,14 @@ public class ResourceProperties { ...@@ -315,14 +315,14 @@ public class ResourceProperties {
private Boolean noStore; private Boolean noStore;
/** /**
* Indicate that once it has become stale, a cache must not use * Indicate that once it has become stale, a cache must not use the response
* the response without re-validating it with the server. * without re-validating it with the server.
*/ */
private Boolean mustRevalidate; private Boolean mustRevalidate;
/** /**
* Indicate intermediaries (caches and others) that they should * Indicate intermediaries (caches and others) that they should not transform the
* not transform the response content. * response content.
*/ */
private Boolean noTransform; private Boolean noTransform;
...@@ -332,34 +332,34 @@ public class ResourceProperties { ...@@ -332,34 +332,34 @@ public class ResourceProperties {
private Boolean cachePublic; private Boolean cachePublic;
/** /**
* Indicate that the response message is intended for a single user * Indicate that the response message is intended for a single user and must not
* and must not be stored by a shared cache. * be stored by a shared cache.
*/ */
private Boolean cachePrivate; private Boolean cachePrivate;
/** /**
* Same meaning as the "must-revalidate" directive, * Same meaning as the "must-revalidate" directive, except that it does not apply
* except that it does not apply to private caches. * to private caches.
*/ */
private Boolean proxyRevalidate; private Boolean proxyRevalidate;
/** /**
* Maximum time the response can be served after it becomes stale, * Maximum time the response can be served after it becomes stale, in seconds if
* in seconds if no duration suffix is not specified. * no duration suffix is not specified.
*/ */
@DefaultDurationUnit(ChronoUnit.SECONDS) @DefaultDurationUnit(ChronoUnit.SECONDS)
private Duration staleWhileRevalidate; private Duration staleWhileRevalidate;
/** /**
* Maximum time the response may be used when errors are encountered, * Maximum time the response may be used when errors are encountered, in seconds
* in seconds if no duration suffix is not specified. * if no duration suffix is not specified.
*/ */
@DefaultDurationUnit(ChronoUnit.SECONDS) @DefaultDurationUnit(ChronoUnit.SECONDS)
private Duration staleIfError; private Duration staleIfError;
/** /**
* Maximum time the response should be cached by shared caches, * Maximum time the response should be cached by shared caches, in seconds if no
* in seconds if no duration suffix is not specified. * duration suffix is not specified.
*/ */
@DefaultDurationUnit(ChronoUnit.SECONDS) @DefaultDurationUnit(ChronoUnit.SECONDS)
private Duration sMaxAge; private Duration sMaxAge;
...@@ -453,44 +453,43 @@ public class ResourceProperties { ...@@ -453,44 +453,43 @@ public class ResourceProperties {
} }
public CacheControl toHttpCacheControl() { public CacheControl toHttpCacheControl() {
CacheControl cc; CacheControl cacheControl = createCacheControl();
if (Boolean.TRUE.equals(this.noStore)) { callIfTrue(this.mustRevalidate, cacheControl, CacheControl::mustRevalidate);
cc = CacheControl.noStore(); callIfTrue(this.noTransform, cacheControl, CacheControl::noTransform);
} callIfTrue(this.cachePublic, cacheControl, CacheControl::cachePublic);
else if (Boolean.TRUE.equals(this.noCache)) { callIfTrue(this.cachePrivate, cacheControl, CacheControl::cachePrivate);
cc = CacheControl.noCache(); callIfTrue(this.proxyRevalidate, cacheControl, CacheControl::proxyRevalidate);
} if (this.staleWhileRevalidate != null) {
else if (this.maxAge != null) { cacheControl.staleWhileRevalidate(this.staleWhileRevalidate.getSeconds(),
cc = CacheControl.maxAge(this.maxAge.getSeconds(), TimeUnit.SECONDS); TimeUnit.SECONDS);
}
else {
cc = CacheControl.empty();
} }
if (Boolean.TRUE.equals(this.mustRevalidate)) { if (this.staleIfError != null) {
cc.mustRevalidate(); cacheControl.staleIfError(this.staleIfError.getSeconds(),
TimeUnit.SECONDS);
} }
if (Boolean.TRUE.equals(this.noTransform)) { if (this.sMaxAge != null) {
cc.noTransform(); cacheControl.sMaxAge(this.sMaxAge.getSeconds(), TimeUnit.SECONDS);
} }
if (Boolean.TRUE.equals(this.cachePublic)) { return cacheControl;
cc.cachePublic();
} }
if (Boolean.TRUE.equals(this.cachePrivate)) {
cc.cachePrivate(); private CacheControl createCacheControl() {
if (Boolean.TRUE.equals(this.noStore)) {
return CacheControl.noStore();
} }
if (Boolean.TRUE.equals(this.proxyRevalidate)) { if (Boolean.TRUE.equals(this.noCache)) {
cc.proxyRevalidate(); return CacheControl.noCache();
} }
if (this.staleWhileRevalidate != null) { if (this.maxAge != null) {
cc.staleWhileRevalidate(this.staleWhileRevalidate.getSeconds(), TimeUnit.SECONDS); return CacheControl.maxAge(this.maxAge.getSeconds(), TimeUnit.SECONDS);
} }
if (this.staleIfError != null) { return CacheControl.empty();
cc.staleIfError(this.staleIfError.getSeconds(), TimeUnit.SECONDS);
} }
if (this.sMaxAge != null) {
cc.sMaxAge(this.sMaxAge.getSeconds(), TimeUnit.SECONDS); private <T> void callIfTrue(Boolean property, T instance, Consumer<T> call) {
if (Boolean.TRUE.equals(property)) {
call.accept(instance);
} }
return cc;
} }
} }
......
...@@ -309,7 +309,8 @@ public class WebMvcAutoConfiguration { ...@@ -309,7 +309,8 @@ public class WebMvcAutoConfiguration {
return; return;
} }
Duration cachePeriod = this.resourceProperties.getCachePeriod(); Duration cachePeriod = this.resourceProperties.getCachePeriod();
CacheControl cacheControl = this.resourceProperties.getCacheControl().toHttpCacheControl(); CacheControl cacheControl = this.resourceProperties.getCacheControl()
.toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) { if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration( customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**") registry.addResourceHandler("/webjars/**")
......
...@@ -57,7 +57,8 @@ public class ReactiveSessionAutoConfigurationRedisTests ...@@ -57,7 +57,8 @@ public class ReactiveSessionAutoConfigurationRedisTests
this.contextRunner.withPropertyValues("spring.session.store-type=redis") this.contextRunner.withPropertyValues("spring.session.store-type=redis")
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
RedisReactiveAutoConfiguration.class)) RedisReactiveAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:", RedisFlushMode.ON_SAVE)); .run(validateSpringSessionUsesRedis("spring:session:",
RedisFlushMode.ON_SAVE));
} }
@Test @Test
...@@ -67,7 +68,8 @@ public class ReactiveSessionAutoConfigurationRedisTests ...@@ -67,7 +68,8 @@ public class ReactiveSessionAutoConfigurationRedisTests
ReactiveMongoOperationsSessionRepository.class)) ReactiveMongoOperationsSessionRepository.class))
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
RedisReactiveAutoConfiguration.class)) RedisReactiveAutoConfiguration.class))
.run(validateSpringSessionUsesRedis("spring:session:", RedisFlushMode.ON_SAVE)); .run(validateSpringSessionUsesRedis("spring:session:",
RedisFlushMode.ON_SAVE));
} }
@Test @Test
......
...@@ -24,6 +24,7 @@ import org.junit.rules.ExpectedException; ...@@ -24,6 +24,7 @@ import org.junit.rules.ExpectedException;
import org.springframework.boot.autoconfigure.web.ResourceProperties.CacheControlProperties; import org.springframework.boot.autoconfigure.web.ResourceProperties.CacheControlProperties;
import org.springframework.boot.testsupport.assertj.Matched; import org.springframework.boot.testsupport.assertj.Matched;
import org.springframework.http.CacheControl;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.endsWith;
...@@ -78,42 +79,42 @@ public class ResourcePropertiesTests { ...@@ -78,42 +79,42 @@ public class ResourcePropertiesTests {
@Test @Test
public void emptyCacheControl() { public void emptyCacheControl() {
CacheControlProperties cacheControl = new CacheControlProperties(); CacheControlProperties cacheControlProperties = new CacheControlProperties();
this.properties.setCacheControl(cacheControl); this.properties.setCacheControl(cacheControlProperties);
assertThat(this.properties.getCacheControl().toHttpCacheControl().getHeaderValue()).isNull(); CacheControl cacheControl = this.properties.getCacheControl()
.toHttpCacheControl();
assertThat(cacheControl.getHeaderValue()).isNull();
} }
@Test @Test
public void cacheControlAllPropertiesSet() { public void cacheControlAllPropertiesSet() {
CacheControlProperties cacheControl = new CacheControlProperties(); CacheControlProperties cacheControlProperties = new CacheControlProperties();
cacheControl.setMaxAge(Duration.ofSeconds(4)); cacheControlProperties.setMaxAge(Duration.ofSeconds(4));
cacheControl.setCachePrivate(true); cacheControlProperties.setCachePrivate(true);
cacheControl.setCachePublic(true); cacheControlProperties.setCachePublic(true);
cacheControl.setMustRevalidate(true); cacheControlProperties.setMustRevalidate(true);
cacheControl.setNoTransform(true); cacheControlProperties.setNoTransform(true);
cacheControl.setProxyRevalidate(true); cacheControlProperties.setProxyRevalidate(true);
cacheControl.setsMaxAge(Duration.ofSeconds(5)); cacheControlProperties.setsMaxAge(Duration.ofSeconds(5));
cacheControl.setStaleIfError(Duration.ofSeconds(6)); cacheControlProperties.setStaleIfError(Duration.ofSeconds(6));
cacheControl.setStaleWhileRevalidate(Duration.ofSeconds(7)); cacheControlProperties.setStaleWhileRevalidate(Duration.ofSeconds(7));
this.properties.setCacheControl(cacheControl); this.properties.setCacheControl(cacheControlProperties);
assertThat(this.properties.getCacheControl().toHttpCacheControl().getHeaderValue()).isEqualTo( CacheControl cacheControl = this.properties.getCacheControl()
"max-age=4, must-revalidate, no-transform, public, private, proxy-revalidate," + .toHttpCacheControl();
" s-maxage=5, stale-if-error=6, stale-while-revalidate=7"); assertThat(cacheControl.getHeaderValue()).isEqualTo(
"max-age=4, must-revalidate, no-transform, public, private, proxy-revalidate,"
+ " s-maxage=5, stale-if-error=6, stale-while-revalidate=7");
} }
@Test @Test
public void invalidCacheControlCombination() { public void invalidCacheControlCombination() {
CacheControlProperties cacheControl = new CacheControlProperties(); CacheControlProperties cacheControlProperties = new CacheControlProperties();
cacheControl.setMaxAge(Duration.ofSeconds(4)); cacheControlProperties.setMaxAge(Duration.ofSeconds(4));
cacheControl.setNoStore(true); cacheControlProperties.setNoStore(true);
this.properties.setCacheControl(cacheControl); this.properties.setCacheControl(cacheControlProperties);
assertThat(this.properties.getCacheControl().toHttpCacheControl().getHeaderValue()).isEqualTo("no-store"); CacheControl cacheControl = this.properties.getCacheControl()
} .toHttpCacheControl();
assertThat(cacheControl.getHeaderValue()).isEqualTo("no-store");
@Test
public void cacheControlNoPropertiesSet() {
this.properties.setCacheControl(new CacheControlProperties());
assertThat(this.properties.getCacheControl().toHttpCacheControl().getHeaderValue()).isNull();
} }
} }
...@@ -810,15 +810,15 @@ public class WebMvcAutoConfigurationTests { ...@@ -810,15 +810,15 @@ public class WebMvcAutoConfigurationTests {
} }
private void assertCachePeriod(AssertableWebApplicationContext context) { private void assertCachePeriod(AssertableWebApplicationContext context) {
Map<String, Object> handlerMap = getHandlerMap(context Map<String, Object> handlerMap = getHandlerMap(
.getBean("resourceHandlerMapping", HandlerMapping.class)); context.getBean("resourceHandlerMapping", HandlerMapping.class));
assertThat(handlerMap).hasSize(2); assertThat(handlerMap).hasSize(2);
for (Object handler : handlerMap.keySet()) { for (Object handler : handlerMap.keySet()) {
if (handler instanceof ResourceHttpRequestHandler) { if (handler instanceof ResourceHttpRequestHandler) {
assertThat(((ResourceHttpRequestHandler) handler) assertThat(((ResourceHttpRequestHandler) handler).getCacheSeconds())
.getCacheSeconds()).isEqualTo(-1); .isEqualTo(-1);
assertThat(((ResourceHttpRequestHandler) handler) assertThat(((ResourceHttpRequestHandler) handler).getCacheControl())
.getCacheControl()).isEqualToComparingFieldByField( .isEqualToComparingFieldByField(
CacheControl.maxAge(5, TimeUnit.SECONDS)); CacheControl.maxAge(5, TimeUnit.SECONDS));
} }
} }
...@@ -835,17 +835,16 @@ public class WebMvcAutoConfigurationTests { ...@@ -835,17 +835,16 @@ public class WebMvcAutoConfigurationTests {
} }
private void assertCacheControl(AssertableWebApplicationContext context) { private void assertCacheControl(AssertableWebApplicationContext context) {
Map<String, Object> handlerMap = getHandlerMap(context Map<String, Object> handlerMap = getHandlerMap(
.getBean("resourceHandlerMapping", HandlerMapping.class)); context.getBean("resourceHandlerMapping", HandlerMapping.class));
assertThat(handlerMap).hasSize(2); assertThat(handlerMap).hasSize(2);
for (Object handler : handlerMap.keySet()) { for (Object handler : handlerMap.keySet()) {
if (handler instanceof ResourceHttpRequestHandler) { if (handler instanceof ResourceHttpRequestHandler) {
assertThat(((ResourceHttpRequestHandler) handler) assertThat(((ResourceHttpRequestHandler) handler).getCacheSeconds())
.getCacheSeconds()).isEqualTo(-1); .isEqualTo(-1);
assertThat(((ResourceHttpRequestHandler) handler) assertThat(((ResourceHttpRequestHandler) handler).getCacheControl())
.getCacheControl()).isEqualToComparingFieldByField( .isEqualToComparingFieldByField(CacheControl
CacheControl.maxAge(5, TimeUnit.SECONDS) .maxAge(5, TimeUnit.SECONDS).proxyRevalidate());
.proxyRevalidate());
} }
} }
} }
...@@ -896,7 +895,6 @@ public class WebMvcAutoConfigurationTests { ...@@ -896,7 +895,6 @@ public class WebMvcAutoConfigurationTests {
return Collections.emptyMap(); return Collections.emptyMap();
} }
@Configuration @Configuration
protected static class ViewConfig { protected static class ViewConfig {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment