diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java index a7d18cddf84..0537653e99e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java @@ -87,25 +87,21 @@ public class ServletWebServerFactoryAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework") + @ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class) static class ForwardedHeaderFilterConfiguration { @Bean @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") @ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class) - public FilterRegistrationBean tomcatForwardedHeaderFilter( - ServerProperties serverProperties) { - return createForwardedHeaderFilter(serverProperties.getTomcat().isUseRelativeRedirects()); + ForwardedHeaderFilterCustomizer tomcatForwardedHeaderFilterCustomizer(ServerProperties serverProperties) { + return (filter) -> filter.setRelativeRedirects(serverProperties.getTomcat().isUseRelativeRedirects()); } @Bean - @ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class) - public FilterRegistrationBean defaultForwardedHeaderFilter() { - return createForwardedHeaderFilter(false); - } - - private FilterRegistrationBean createForwardedHeaderFilter(boolean relativeRedirects) { + FilterRegistrationBean forwardedHeaderFilter( + ObjectProvider customizerProvider) { ForwardedHeaderFilter filter = new ForwardedHeaderFilter(); - filter.setRelativeRedirects(relativeRedirects); + customizerProvider.ifAvailable((customizer) -> customizer.customize(filter)); FilterRegistrationBean registration = new FilterRegistrationBean<>(filter); registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR); registration.setOrder(Ordered.HIGHEST_PRECEDENCE); @@ -114,6 +110,12 @@ public class ServletWebServerFactoryAutoConfiguration { } + interface ForwardedHeaderFilterCustomizer { + + void customize(ForwardedHeaderFilter filter); + + } + /** * Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via * {@link ImportBeanDefinitionRegistrar} for early registration. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java index ffdc3071a1e..c30bc1c0cfc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java @@ -57,7 +57,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.filter.ForwardedHeaderFilter; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.FrameworkServlet; @@ -353,6 +352,7 @@ class ServletWebServerFactoryAutoConfigurationTests { assertThat(context).hasSingleBean(FilterRegistrationBean.class); Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(false); }); } @@ -376,11 +376,24 @@ class ServletWebServerFactoryAutoConfigurationTests { .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) .withPropertyValues("server.forward-headers-strategy=framework", "server.tomcat.use-relative-redirects=true"); - runner.run((context) -> { Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - Boolean relativeRedirects = (Boolean) ReflectionTestUtils.getField(filter, "relativeRedirects"); - assertThat(relativeRedirects).isTrue(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(true); + }); + } + + @Test + void relativeRedirectsShouldNotBeEnabledWhenUsingTomcatContainerAndNotUsingRelativeRedirects() { + WebApplicationContextRunner runner = new WebApplicationContextRunner( + AnnotationConfigServletWebServerApplicationContext::new) + .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) + .withPropertyValues("server.forward-headers-strategy=framework", + "server.tomcat.use-relative-redirects=false"); + runner.run((context) -> { + Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(false); }); } @@ -391,11 +404,10 @@ class ServletWebServerFactoryAutoConfigurationTests { .withClassLoader(new FilteredClassLoader(Tomcat.class)) .withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class)) .withPropertyValues("server.forward-headers-strategy=framework"); - runner.run((context) -> { Filter filter = context.getBean(FilterRegistrationBean.class).getFilter(); - Boolean relativeRedirects = (Boolean) ReflectionTestUtils.getField(filter, "relativeRedirects"); - assertThat(relativeRedirects).isFalse(); + assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class); + assertThat(filter).extracting("relativeRedirects").isEqualTo(false); }); }