diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/httpheadersfilters.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/httpheadersfilters.adoc index a4a50bba..ea6a5a65 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/httpheadersfilters.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/httpheadersfilters.adoc @@ -5,11 +5,11 @@ [[forwarded-headers-filter]] == Forwarded Headers Filter -The `Forwarded` Headers Filter creates a `Forwarded` header to send to the downstream service. It adds the `Host` header, scheme and port of the current request to any existing `Forwarded` header. To activate this filter set the `spring.cloud.gateway.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. +The `Forwarded` Headers Filter creates a `Forwarded` header to send to the downstream service. It adds the `Host` header, scheme and port of the current request to any existing `Forwarded` header. To activate this filter set the `spring.cloud.gateway.server.webflux.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. The `Forwarded by` header part can be enabled by setting the following property to true (defaults to false): -- `spring.cloud.gateway.forwarded.by.enabled=true` +- `spring.cloud.gateway.server.webflux.forwarded.by.enabled=true` [[removehopbyhop-headers-filter]] == RemoveHopByHop Headers Filter @@ -25,25 +25,25 @@ The `RemoveHopByHop` Headers Filter removes headers from forwarded requests. The * Transfer-Encoding * Upgrade -To change this, set the `spring.cloud.gateway.filter.remove-hop-by-hop.headers` property to the list of header names to remove. +To change this, set the `spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.headers` property to the list of header names to remove. [[xforwarded-headers-filter]] == XForwarded Headers Filter -The `XForwarded` Headers Filter creates various `X-Forwarded-*` headers to send to the downstream service. It uses the `Host` header, scheme, port and path of the current request to create the various headers. To activate this filter set the `spring.cloud.gateway.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. +The `XForwarded` Headers Filter creates various `X-Forwarded-*` headers to send to the downstream service. It uses the `Host` header, scheme, port and path of the current request to create the various headers. To activate this filter set the `spring.cloud.gateway.server.webflux.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. Creating of individual headers can be controlled by the following boolean properties (defaults to true): -- `spring.cloud.gateway.x-forwarded.for-enabled` -- `spring.cloud.gateway.x-forwarded.host-enabled` -- `spring.cloud.gateway.x-forwarded.port-enabled` -- `spring.cloud.gateway.x-forwarded.proto-enabled` -- `spring.cloud.gateway.x-forwarded.prefix-enabled` +- `spring.cloud.gateway.server.webflux.x-forwarded.for-enabled` +- `spring.cloud.gateway.server.webflux.x-forwarded.host-enabled` +- `spring.cloud.gateway.server.webflux.x-forwarded.port-enabled` +- `spring.cloud.gateway.server.webflux.x-forwarded.proto-enabled` +- `spring.cloud.gateway.server.webflux.x-forwarded.prefix-enabled` Appending multiple headers can be controlled by the following boolean properties (defaults to true): -- `spring.cloud.gateway.x-forwarded.for-append` -- `spring.cloud.gateway.x-forwarded.host-append` -- `spring.cloud.gateway.x-forwarded.port-append` -- `spring.cloud.gateway.x-forwarded.proto-append` -- `spring.cloud.gateway.x-forwarded.prefix-append` +- `spring.cloud.gateway.server.webflux.x-forwarded.for-append` +- `spring.cloud.gateway.server.webflux.x-forwarded.host-append` +- `spring.cloud.gateway.server.webflux.x-forwarded.port-append` +- `spring.cloud.gateway.server.webflux.x-forwarded.proto-append` +- `spring.cloud.gateway.server.webflux.x-forwarded.prefix-append` diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/httpheadersfilters.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/httpheadersfilters.adoc index d60c00d7..cc11d566 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/httpheadersfilters.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/httpheadersfilters.adoc @@ -5,7 +5,7 @@ HttpHeadersFilters are applied to the requests before sending them downstream, s [[forwarded-headers-filter]] == Forwarded Headers Filter -The `Forwarded` Headers Filter creates a `Forwarded` header to send to the downstream service. It adds the `Host` header, scheme and port of the current request to any existing `Forwarded` header. To activate this filter set the `spring.cloud.gateway.mvc.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. +The `Forwarded` Headers Filter creates a `Forwarded` header to send to the downstream service. It adds the `Host` header, scheme and port of the current request to any existing `Forwarded` header. To activate this filter set the `spring.cloud.gateway.server.webmvc.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. [[removehopbyhop-headers-filter]] == RemoveHopByHop Headers Filter @@ -25,21 +25,21 @@ The `RemoveHopByHop` Headers Filter removes headers from forwarded requests. The [[xforwarded-headers-filter]] == XForwarded Headers Filter -The `XForwarded` Headers Filter creates various `X-Forwarded-*` headers to send to the downstream service. It uses the `Host` header, scheme, port and path of the current request to create the various headers. To activate this filter set the `spring.cloud.gateway.mvc.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. +The `XForwarded` Headers Filter creates various `X-Forwarded-*` headers to send to the downstream service. It uses the `Host` header, scheme, port and path of the current request to create the various headers. To activate this filter set the `spring.cloud.gateway.server.webmvc.trusted-proxies` property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the `Forwarded` header. Creating of individual headers can be controlled by the following boolean properties (defaults to true): -- `spring.cloud.gateway.x-forwarded.for-enabled` -- `spring.cloud.gateway.x-forwarded.host-enabled` -- `spring.cloud.gateway.x-forwarded.port-enabled` -- `spring.cloud.gateway.x-forwarded.proto-enabled` -- `spring.cloud.gateway.x-forwarded.prefix-enabled` +- `spring.cloud.gateway.server.webmvc.x-forwarded.for-enabled` +- `spring.cloud.gateway.server.webmvc.x-forwarded.host-enabled` +- `spring.cloud.gateway.server.webmvc.x-forwarded.port-enabled` +- `spring.cloud.gateway.server.webmvc.x-forwarded.proto-enabled` +- `spring.cloud.gateway.server.webmvc.x-forwarded.prefix-enabled` Appending multiple headers can be controlled by the following boolean properties (defaults to true): -- `spring.cloud.gateway.x-forwarded.for-append` -- `spring.cloud.gateway.x-forwarded.host-append` -- `spring.cloud.gateway.x-forwarded.port-append` -- `spring.cloud.gateway.x-forwarded.proto-append` -- `spring.cloud.gateway.x-forwarded.prefix-append` +- `spring.cloud.gateway.server.webmvc.x-forwarded.for-append` +- `spring.cloud.gateway.server.webmvc.x-forwarded.host-append` +- `spring.cloud.gateway.server.webmvc.x-forwarded.port-append` +- `spring.cloud.gateway.server.webmvc.x-forwarded.proto-append` +- `spring.cloud.gateway.server.webmvc.x-forwarded.prefix-append` diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java index 8ebb7f77..48f809cc 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilter.java @@ -82,9 +82,10 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request } private XForwardedRequestHeadersFilter(XForwardedRequestHeadersFilterProperties props, - TrustedProxies trustedProxies) { + TrustedProxies trustedProxies) { + Assert.notNull(props, "XForwardedRequestHeadersFilterProperties must not be null"); Assert.notNull(trustedProxies, "trustedProxies must not be null"); - + this.properties = props; this.trustedProxies = trustedProxies; } diff --git a/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/additional-spring-configuration-metadata.json index ce35f3ef..b9a93a26 100644 --- a/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-gateway-server-mvc/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -365,6 +365,18 @@ "defaultValue": "jdk", "deprecated": true, "deprecation": {} + }, + { + "name": "spring.cloud.gateway.mvc.trusted-proxies", + "type": "java.lang.String", + "description": "Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header.", + "sourceType": "org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties", + "defaultValue": true, + "deprecated": true, + "deprecation": { + "replacement": "spring.cloud.gateway.server.webmvc.trusted-proxies", + "since": "4.3.0" + } } ] } diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilterTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilterTests.java index b5174e55..f823bde8 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilterTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilterTests.java @@ -27,7 +27,16 @@ import java.util.Optional; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration; +import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.cloud.gateway.server.mvc.GatewayServerMvcAutoConfiguration; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.cloud.gateway.server.mvc.filter.ForwardedRequestHeadersFilter.Forwarded; +import org.springframework.cloud.gateway.server.mvc.predicate.PredicateAutoConfiguration; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -53,6 +62,31 @@ public class ForwardedRequestHeadersFilterTests { return map; } + @Test + public void trustedProxiesConditionMatches() { + new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, + SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + GatewayServerMvcAutoConfiguration.class, FilterAutoConfiguration.class, + PredicateAutoConfiguration.class)) + .withPropertyValues(GatewayMvcProperties.PREFIX + ".trusted-proxies=11\\.0\\.0\\..*") + .run(context -> { + assertThat(context).hasSingleBean(ForwardedRequestHeadersFilter.class); + }); + } + + @Test + public void trustedProxiesConditionDoesNotMatch() { + new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, + SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + GatewayServerMvcAutoConfiguration.class, FilterAutoConfiguration.class, + PredicateAutoConfiguration.class)) + .run(context -> { + assertThat(context).doesNotHaveBean(ForwardedRequestHeadersFilter.class); + }); + } + @Test public void forwardedHeaderDoesNotExist() { MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java index f9c27a91..e636b578 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java @@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.cloud.gateway.server.mvc.GatewayServerMvcAutoConfiguration; import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; +import org.springframework.cloud.gateway.server.mvc.predicate.PredicateAutoConfiguration; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -71,7 +72,8 @@ public class XForwardedRequestHeadersFilterTests { new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, - GatewayServerMvcAutoConfiguration.class)) + GatewayServerMvcAutoConfiguration.class, FilterAutoConfiguration.class, + PredicateAutoConfiguration.class)) .withPropertyValues(GatewayMvcProperties.PREFIX + ".trusted-proxies=11\\.0\\.0\\..*") .run(context -> { assertThat(context).hasSingleBean(XForwardedRequestHeadersFilter.class); @@ -83,7 +85,8 @@ public class XForwardedRequestHeadersFilterTests { new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, - GatewayServerMvcAutoConfiguration.class)) + GatewayServerMvcAutoConfiguration.class, FilterAutoConfiguration.class, + PredicateAutoConfiguration.class)) .run(context -> { assertThat(context).doesNotHaveBean(XForwardedRequestHeadersFilter.class); }); diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java index aa6afacc..ba577195 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java @@ -323,7 +323,8 @@ public class GatewayAutoConfiguration { @Bean @Conditional(TrustedProxies.ForwardedTrustedProxiesCondition.class) - public ForwardedHeadersFilter forwardedHeadersFilter(Environment env, ServerProperties serverProperties, GatewayProperties properties) { + public ForwardedHeadersFilter forwardedHeadersFilter(Environment env, ServerProperties serverProperties, + GatewayProperties properties) { boolean forwardedByEnabled = env.getProperty("spring.cloud.gateway.server.webflux.forwarded.by.enabled", Boolean.class, false); ForwardedHeadersFilter forwardedHeadersFilter = new ForwardedHeadersFilter(properties.getTrustedProxies()); diff --git a/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 13464a13..ed06fd73 100644 --- a/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-gateway-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -2432,6 +2432,18 @@ "replacement": "spring.cloud.gateway.server.webflux.x-forwarded.proto-enabled", "since": "4.3.0" } + }, + { + "name": "spring.cloud.gateway.trusted-proxies", + "type": "java.lang.String", + "description": "Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header.", + "sourceType": "org.springframework.cloud.gateway.config.GatewayProperties", + "defaultValue": true, + "deprecated": true, + "deprecation": { + "replacement": "spring.cloud.gateway.server.webflux.trusted-proxies", + "since": "4.3.0" + } } ] } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java index ceaff580..88c2f8ce 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java @@ -357,8 +357,9 @@ public class GatewayAutoConfigurationTests { .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class, ServerPropertiesConfig.class)) - .withPropertyValues("spring.cloud.gateway.forwarded.enabled=true", - "spring.cloud.gateway.x-forwarded.enabled=true", "spring.cloud.gateway.trusted-proxies=.*") + .withPropertyValues("spring.cloud.gateway.server.webflux.forwarded.enabled=true", + "spring.cloud.gateway.server.webflux.x-forwarded.enabled=true", + "spring.cloud.gateway.server.webflux.trusted-proxies=.*") .run(context -> { assertThat(context).hasSingleBean(XForwardedHeadersFilter.class) .hasSingleBean(ForwardedHeadersFilter.class); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java index a7445aeb..2bfcfee5 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java @@ -66,8 +66,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @SpringBootTest(webEnvironment = RANDOM_PORT, properties = { "spring.cloud.gateway.server.webflux.httpclient.connect-timeout=500", "spring.cloud.gateway.server.webflux.httpclient.response-timeout=2s", - "logging.level.org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory=TRACE" - "spring.cloud.gateway.server.webflux.trusted-proxies=.*", "spring.cloud.gateway.server.webflux.x-forwarded.enabled=true" }) + "logging.level.org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory=TRACE", + "spring.cloud.gateway.server.webflux.trusted-proxies=.*", + "spring.cloud.gateway.server.webflux.x-forwarded.enabled=true" }) @DirtiesContext // default filter AddResponseHeader suppresses bug // https://github.com/spring-cloud/spring-cloud-gateway/issues/1315, diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilterTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilterTests.java index 04283344..dfe83d1d 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilterTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilterTests.java @@ -264,7 +264,7 @@ public class ForwardedHeadersFilterTests { new ReactiveWebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, SslAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) - .withPropertyValues("spring.cloud.gateway.trusted-proxies=11\\.0\\.0\\..*") + .withPropertyValues("spring.cloud.gateway.server.webflux.trusted-proxies=11\\.0\\.0\\..*") .run(context -> { assertThat(context).hasSingleBean(ForwardedHeadersFilter.class); }); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java index 2ac25e73..d52feb12 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/GatewayIntegrationTests.java @@ -63,7 +63,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen import static org.springframework.cloud.gateway.test.TestUtils.getMap; @SpringBootTest(webEnvironment = RANDOM_PORT, - properties = { "spring.cloud.gateway.server.webflux.forwarded.by.enabled=true", "spring.cloud.gateway.server.webflux.forwarded.enabled=true", "spring.cloud.gateway.server.webflux.x-forwarded.enabled=true", + properties = { "spring.cloud.gateway.server.webflux.forwarded.by.enabled=true", + "spring.cloud.gateway.server.webflux.forwarded.enabled=true", + "spring.cloud.gateway.server.webflux.x-forwarded.enabled=true", "spring.cloud.gateway.server.webflux.trusted-proxies=.*", "logging.level.org.springframework.cloud.gateway.filter.headers=TRACE" }) @DirtiesContext