From ca9721f4ee8096beaaae3d2e57c59148fcd5a065 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Fri, 9 May 2025 16:29:56 -0400 Subject: [PATCH] Migrates proxy-exchange-webmvc properties to new namespace from spring.cloud.gateway.proxy to spring.cloud.gateway.proxy-exchange.webmvc Fixes gh-3361 --- spring-cloud-gateway-mvc/pom.xml | 5 + .../config/ProxyExchangeWebMvcProperties.java | 116 ++++++++++++++++++ .../gateway/mvc/config/ProxyProperties.java | 10 +- .../ProxyResponseAutoConfiguration.java | 16 +-- ...xchangeWebmvcPropertiesMigrationTests.java | 52 ++++++++ .../application-propertiesmigrationtests.yml | 10 ++ 6 files changed, 200 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebMvcProperties.java create mode 100644 spring-cloud-gateway-mvc/src/test/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebmvcPropertiesMigrationTests.java create mode 100644 spring-cloud-gateway-mvc/src/test/resources/application-propertiesmigrationtests.yml diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index 14d0d2aa..e339f496 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -41,6 +41,11 @@ 4.5.14 test + + org.springframework.boot + spring-boot-properties-migrator + test + org.springframework.boot spring-boot-configuration-processor diff --git a/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebMvcProperties.java b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebMvcProperties.java new file mode 100644 index 00000000..12e75015 --- /dev/null +++ b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebMvcProperties.java @@ -0,0 +1,116 @@ +/* + * Copyright 2016-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.gateway.mvc.config; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.gateway.mvc.ProxyExchange; +import org.springframework.http.HttpHeaders; + +/** + * Configuration properties for the {@link ProxyExchange} argument handler in + * @RequestMapping methods. + * + * @author Dave Syer + * @author Tim Ysewyn + * @author Joris Kuipers + * + */ +@ConfigurationProperties(ProxyExchangeWebMvcProperties.PREFIX) +public class ProxyExchangeWebMvcProperties { + + /** + * Properties prefix. + */ + public static final String PREFIX = "spring.cloud.gateway.proxy-exchange.webmvc"; + + /** + * Contains headers that are considered sensitive by default. + */ + public static Set DEFAULT_SENSITIVE = Set.of("cookie", "authorization"); + + /** + * Contains headers that are skipped by default. + */ + public static Set DEFAULT_SKIPPED = Set.of("content-length", "host"); + + /** + * Fixed header values that will be added to all downstream requests. + */ + private Map headers = new LinkedHashMap<>(); + + /** + * A set of header names that should be sent downstream by default. + */ + private Set autoForward = new HashSet<>(); + + /** + * A set of sensitive header names that will not be sent downstream by default. + */ + private Set sensitive = DEFAULT_SENSITIVE; + + /** + * A set of header names that will not be sent downstream because they could be + * problematic. + */ + private Set skipped = DEFAULT_SKIPPED; + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public Set getAutoForward() { + return autoForward; + } + + public void setAutoForward(Set autoForward) { + this.autoForward = autoForward; + } + + public Set getSensitive() { + return sensitive; + } + + public void setSensitive(Set sensitive) { + this.sensitive = sensitive; + } + + public Set getSkipped() { + return skipped; + } + + public void setSkipped(Set skipped) { + this.skipped = skipped; + } + + public HttpHeaders convertHeaders() { + HttpHeaders headers = new HttpHeaders(); + for (String key : this.headers.keySet()) { + headers.set(key, this.headers.get(key)); + } + return headers; + } + +} diff --git a/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyProperties.java b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyProperties.java index 59296583..e9b546bf 100644 --- a/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyProperties.java +++ b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyProperties.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.cloud.gateway.mvc.ProxyExchange; import org.springframework.http.HttpHeaders; @@ -32,8 +33,10 @@ import org.springframework.http.HttpHeaders; * @author Dave Syer * @author Tim Ysewyn * @author Joris Kuipers - * + * @author Spencer Gibb + * @deprecated {@link ProxyExchangeWebMvcProperties} */ +@Deprecated @ConfigurationProperties("spring.cloud.gateway.proxy") public class ProxyProperties { @@ -68,6 +71,7 @@ public class ProxyProperties { */ private Set skipped = DEFAULT_SKIPPED; + @DeprecatedConfigurationProperty(replacement = ProxyExchangeWebMvcProperties.PREFIX + ".headers", since = "4.3.0") public Map getHeaders() { return headers; } @@ -76,6 +80,8 @@ public class ProxyProperties { this.headers = headers; } + @DeprecatedConfigurationProperty(replacement = ProxyExchangeWebMvcProperties.PREFIX + ".auto-forward", + since = "4.3.0") public Set getAutoForward() { return autoForward; } @@ -84,6 +90,7 @@ public class ProxyProperties { this.autoForward = autoForward; } + @DeprecatedConfigurationProperty(replacement = ProxyExchangeWebMvcProperties.PREFIX + ".sensitive", since = "4.3.0") public Set getSensitive() { return sensitive; } @@ -92,6 +99,7 @@ public class ProxyProperties { this.sensitive = sensitive; } + @DeprecatedConfigurationProperty(replacement = ProxyExchangeWebMvcProperties.PREFIX + ".skipped", since = "4.3.0") public Set getSkipped() { return skipped; } diff --git a/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyResponseAutoConfiguration.java b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyResponseAutoConfiguration.java index 0a840d78..b7cfeb18 100644 --- a/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyResponseAutoConfiguration.java +++ b/spring-cloud-gateway-mvc/src/main/java/org/springframework/cloud/gateway/mvc/config/ProxyResponseAutoConfiguration.java @@ -57,7 +57,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication @ConditionalOnClass({ HandlerMethodReturnValueHandler.class }) -@EnableConfigurationProperties(ProxyProperties.class) +@EnableConfigurationProperties({ ProxyExchangeWebMvcProperties.class, ProxyProperties.class }) public class ProxyResponseAutoConfiguration implements WebMvcConfigurer { @Autowired @@ -66,7 +66,7 @@ public class ProxyResponseAutoConfiguration implements WebMvcConfigurer { @Bean @ConditionalOnMissingBean public ProxyExchangeArgumentResolver proxyExchangeArgumentResolver(Optional optional, - ProxyProperties proxy) { + ProxyExchangeWebMvcProperties properties) { RestTemplateBuilder builder = optional.orElse(new RestTemplateBuilder()); RestTemplate template = builder.build(); template.setErrorHandler(new NoOpResponseErrorHandler()); @@ -77,14 +77,14 @@ public class ProxyResponseAutoConfiguration implements WebMvcConfigurer { } }); ProxyExchangeArgumentResolver resolver = new ProxyExchangeArgumentResolver(template); - resolver.setHeaders(proxy.convertHeaders()); - resolver.setAutoForwardedHeaders(proxy.getAutoForward()); + resolver.setHeaders(properties.convertHeaders()); + resolver.setAutoForwardedHeaders(properties.getAutoForward()); Set excludedHeaderNames = new HashSet<>(); - if (proxy.getSensitive() != null) { - excludedHeaderNames.addAll(proxy.getSensitive()); + if (properties.getSensitive() != null) { + excludedHeaderNames.addAll(properties.getSensitive()); } - if (proxy.getSkipped() != null) { - excludedHeaderNames.addAll(proxy.getSkipped()); + if (properties.getSkipped() != null) { + excludedHeaderNames.addAll(properties.getSkipped()); } resolver.setExcluded(excludedHeaderNames); return resolver; diff --git a/spring-cloud-gateway-mvc/src/test/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebmvcPropertiesMigrationTests.java b/spring-cloud-gateway-mvc/src/test/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebmvcPropertiesMigrationTests.java new file mode 100644 index 00000000..4c15b7f3 --- /dev/null +++ b/spring-cloud-gateway-mvc/src/test/java/org/springframework/cloud/gateway/mvc/config/ProxyExchangeWebmvcPropertiesMigrationTests.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.gateway.mvc.config; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; + +import static org.assertj.core.api.Assertions.assertThat; + +@SuppressWarnings("unchecked") +@SpringBootTest(properties = {}, webEnvironment = WebEnvironment.RANDOM_PORT) +@ActiveProfiles("propertiesmigrationtests") +public class ProxyExchangeWebmvcPropertiesMigrationTests { + + @Autowired + ProxyExchangeWebMvcProperties properties; + + @Test + public void deprecatedRoutePropertiesWork() { + assertThat(properties.getHeaders()).hasSize(2); + assertThat(properties.getAutoForward()).hasSize(2); + assertThat(properties.getSensitive()).hasSize(2); + assertThat(properties.getSkipped()).hasSize(3); + } + + @SpringBootConfiguration + @EnableAutoConfiguration + protected static class TestConfiguration { + + } + +} diff --git a/spring-cloud-gateway-mvc/src/test/resources/application-propertiesmigrationtests.yml b/spring-cloud-gateway-mvc/src/test/resources/application-propertiesmigrationtests.yml new file mode 100644 index 00000000..d6b6dfe5 --- /dev/null +++ b/spring-cloud-gateway-mvc/src/test/resources/application-propertiesmigrationtests.yml @@ -0,0 +1,10 @@ +spring.cloud.gateway.proxy: + headers: + X-Foo: xfooval + X-Bar: xbarval + auto-forward: X-FWD1, X-FWD2 + sensitive: X-S1, X-S21 + skipped: X-SK1, X-SK2, X-SK3 +logging: + level: + org.springframework.cloud.gateway.server.mvc: TRACE