From 9e5f171510740ab2166896c6222ccaa0e4a82601 Mon Sep 17 00:00:00 2001 From: artsiom Date: Tue, 9 Oct 2018 18:49:22 +0300 Subject: [PATCH] Support cachecontrol config property in WebFlux Closes gh-14724 --- .../reactive/WebFluxAutoConfiguration.java | 16 +++--- .../WebFluxAutoConfigurationTests.java | 53 +++++++++++++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) 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 1e250df657..2eb77ddb1c 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 @@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.web.reactive; import java.time.Duration; import java.util.Collection; -import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -50,7 +49,6 @@ import org.springframework.core.convert.converter.GenericConverter; import org.springframework.format.Formatter; import org.springframework.format.FormatterRegistry; import org.springframework.format.support.FormattingConversionService; -import org.springframework.http.CacheControl; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.ClassUtils; import org.springframework.validation.Validator; @@ -151,14 +149,16 @@ public class WebFluxAutoConfiguration { return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); + ResourceProperties.Cache.Cachecontrol cacheControl = this.resourceProperties + .getCache().getCachecontrol(); if (!registry.hasMappingForPattern("/webjars/**")) { ResourceHandlerRegistration registration = registry .addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); - if (cachePeriod != null) { - registration.setCacheControl(CacheControl - .maxAge(cachePeriod.toMillis(), TimeUnit.MILLISECONDS)); + if (cachePeriod != null && cacheControl.getMaxAge() == null) { + cacheControl.setMaxAge(cachePeriod); } + registration.setCacheControl(cacheControl.toHttpCacheControl()); customizeResourceHandlerRegistration(registration); } String staticPathPattern = this.webFluxProperties.getStaticPathPattern(); @@ -166,10 +166,10 @@ public class WebFluxAutoConfiguration { ResourceHandlerRegistration registration = registry .addResourceHandler(staticPathPattern).addResourceLocations( this.resourceProperties.getStaticLocations()); - if (cachePeriod != null) { - registration.setCacheControl(CacheControl - .maxAge(cachePeriod.toMillis(), TimeUnit.MILLISECONDS)); + if (cachePeriod != null && cacheControl.getMaxAge() == null) { + cacheControl.setMaxAge(cachePeriod); } + registration.setCacheControl(cacheControl.toHttpCacheControl()); customizeResourceHandlerRegistration(registration); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index 90cc548667..7677434c79 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -16,8 +16,11 @@ package org.springframework.boot.autoconfigure.web.reactive; +import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.validation.ValidatorFactory; @@ -28,6 +31,7 @@ import org.springframework.beans.DirectFieldAccessor; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.autoconfigure.validation.ValidatorAdapter; +import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.boot.web.reactive.filter.OrderedHiddenHttpMethodFilter; @@ -38,6 +42,7 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.io.ClassPathResource; import org.springframework.format.support.FormattingConversionService; +import org.springframework.http.CacheControl; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.test.util.ReflectionTestUtils; @@ -58,6 +63,7 @@ import org.springframework.web.reactive.result.method.annotation.RequestMappingH import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.reactive.result.view.ViewResolutionResultHandler; import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.util.pattern.PathPattern; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -406,6 +412,53 @@ public class WebFluxAutoConfigurationTests { }); } + @Test + public void cachePeriod() { + this.contextRunner.withPropertyValues("spring.resources.cache.period:5") + .run(this::assertCachePeriod); + } + + @Test + public void cacheControl() { + this.contextRunner + .withPropertyValues("spring.resources.cache.cachecontrol.max-age:5", + "spring.resources.cache.cachecontrol.proxy-revalidate:true") + .run(this::assertCacheControl); + } + + private void assertCachePeriod(AssertableReactiveWebApplicationContext context) { + Map handlerMap = getHandlerMap( + context.getBean("resourceHandlerMapping", HandlerMapping.class)); + assertThat(handlerMap).hasSize(2); + for (Object handler : handlerMap.values()) { + if (handler instanceof ResourceWebHandler) { + assertThat(((ResourceWebHandler) handler).getCacheControl()) + .isEqualToComparingFieldByField( + CacheControl.maxAge(5, TimeUnit.SECONDS)); + } + } + } + + private Map getHandlerMap(HandlerMapping mapping) { + if (mapping instanceof SimpleUrlHandlerMapping) { + return ((SimpleUrlHandlerMapping) mapping).getHandlerMap(); + } + return Collections.emptyMap(); + } + + private void assertCacheControl(AssertableReactiveWebApplicationContext context) { + Map handlerMap = getHandlerMap( + context.getBean("resourceHandlerMapping", HandlerMapping.class)); + assertThat(handlerMap).hasSize(2); + for (Object handler : handlerMap.values()) { + if (handler instanceof ResourceWebHandler) { + assertThat(((ResourceWebHandler) handler).getCacheControl()) + .isEqualToComparingFieldByField(CacheControl + .maxAge(5, TimeUnit.SECONDS).proxyRevalidate()); + } + } + } + @Configuration protected static class CustomArgumentResolvers {