Skip to content

Commit 92578f1

Browse files
committed
Merge pull request #29333 from terminux
* gh-29333: Polish "Configure ForwardedHeaderFilter with Tomcat's use relative redirects" Configure ForwardedHeaderFilter with Tomcat's use relative redirects Closes gh-29333
2 parents 59799c8 + 64ee544 commit 92578f1

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.java

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -85,15 +85,35 @@ public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCust
8585
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
8686
}
8787

88-
@Bean
89-
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
88+
@Configuration(proxyBeanMethods = false)
9089
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
91-
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
92-
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
93-
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
94-
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
95-
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
96-
return registration;
90+
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
91+
static class ForwardedHeaderFilterConfiguration {
92+
93+
@Bean
94+
@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
95+
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
96+
ForwardedHeaderFilterCustomizer tomcatForwardedHeaderFilterCustomizer(ServerProperties serverProperties) {
97+
return (filter) -> filter.setRelativeRedirects(serverProperties.getTomcat().isUseRelativeRedirects());
98+
}
99+
100+
@Bean
101+
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter(
102+
ObjectProvider<ForwardedHeaderFilterCustomizer> customizerProvider) {
103+
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
104+
customizerProvider.ifAvailable((customizer) -> customizer.customize(filter));
105+
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
106+
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
107+
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
108+
return registration;
109+
}
110+
111+
}
112+
113+
interface ForwardedHeaderFilterCustomizer {
114+
115+
void customize(ForwardedHeaderFilter filter);
116+
97117
}
98118

99119
/**

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfigurationTests.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ void forwardedHeaderFilterShouldBeConfigured() {
352352
assertThat(context).hasSingleBean(FilterRegistrationBean.class);
353353
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
354354
assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class);
355+
assertThat(filter).extracting("relativeRedirects").isEqualTo(false);
355356
});
356357
}
357358

@@ -368,6 +369,48 @@ void forwardedHeaderFilterWhenFilterAlreadyRegisteredShouldBackOff() {
368369
.run((context) -> assertThat(context).hasSingleBean(FilterRegistrationBean.class));
369370
}
370371

372+
@Test
373+
void relativeRedirectsShouldBeEnabledWhenUsingTomcatContainerAndUseRelativeRedirects() {
374+
WebApplicationContextRunner runner = new WebApplicationContextRunner(
375+
AnnotationConfigServletWebServerApplicationContext::new)
376+
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
377+
.withPropertyValues("server.forward-headers-strategy=framework",
378+
"server.tomcat.use-relative-redirects=true");
379+
runner.run((context) -> {
380+
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
381+
assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class);
382+
assertThat(filter).extracting("relativeRedirects").isEqualTo(true);
383+
});
384+
}
385+
386+
@Test
387+
void relativeRedirectsShouldNotBeEnabledWhenUsingTomcatContainerAndNotUsingRelativeRedirects() {
388+
WebApplicationContextRunner runner = new WebApplicationContextRunner(
389+
AnnotationConfigServletWebServerApplicationContext::new)
390+
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
391+
.withPropertyValues("server.forward-headers-strategy=framework",
392+
"server.tomcat.use-relative-redirects=false");
393+
runner.run((context) -> {
394+
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
395+
assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class);
396+
assertThat(filter).extracting("relativeRedirects").isEqualTo(false);
397+
});
398+
}
399+
400+
@Test
401+
void relativeRedirectsShouldNotBeEnabledWhenNotUsingTomcatContainer() {
402+
WebApplicationContextRunner runner = new WebApplicationContextRunner(
403+
AnnotationConfigServletWebServerApplicationContext::new)
404+
.withClassLoader(new FilteredClassLoader(Tomcat.class))
405+
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class))
406+
.withPropertyValues("server.forward-headers-strategy=framework");
407+
runner.run((context) -> {
408+
Filter filter = context.getBean(FilterRegistrationBean.class).getFilter();
409+
assertThat(filter).isInstanceOf(ForwardedHeaderFilter.class);
410+
assertThat(filter).extracting("relativeRedirects").isEqualTo(false);
411+
});
412+
}
413+
371414
private ContextConsumer<AssertableWebApplicationContext> verifyContext() {
372415
return this::verifyContext;
373416
}

0 commit comments

Comments
 (0)