Polish "Configure ForwardedHeaderFilter with Tomcat's use relative redirects"

See gh-29333
This commit is contained in:
Andy Wilkinson 2022-02-09 17:27:13 +00:00
parent cec69feb95
commit 64ee54423a
2 changed files with 31 additions and 17 deletions

View File

@ -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<ForwardedHeaderFilter> 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<ForwardedHeaderFilter> defaultForwardedHeaderFilter() {
return createForwardedHeaderFilter(false);
}
private FilterRegistrationBean<ForwardedHeaderFilter> createForwardedHeaderFilter(boolean relativeRedirects) {
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter(
ObjectProvider<ForwardedHeaderFilterCustomizer> customizerProvider) {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
filter.setRelativeRedirects(relativeRedirects);
customizerProvider.ifAvailable((customizer) -> customizer.customize(filter));
FilterRegistrationBean<ForwardedHeaderFilter> 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.

View File

@ -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);
});
}