From 55166f4ac5b5ce3624474c1d60b7d50633a924a7 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Sat, 24 May 2025 18:56:22 +0000 Subject: [PATCH 01/20] Bumping versions --- .../cloud/gateway/server/mvc/VanillaRouterFunctionTests.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/VanillaRouterFunctionTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/VanillaRouterFunctionTests.java index 81d1128c..180b3d9a 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/VanillaRouterFunctionTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/VanillaRouterFunctionTests.java @@ -43,8 +43,7 @@ import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFuncti import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host; @SuppressWarnings("unchecked") -@SpringBootTest(properties = { "spring.http.client.factory=jdk" }, - webEnvironment = WebEnvironment.RANDOM_PORT) +@SpringBootTest(properties = { "spring.http.client.factory=jdk" }, webEnvironment = WebEnvironment.RANDOM_PORT) @ContextConfiguration(initializers = HttpbinTestcontainers.class) public class VanillaRouterFunctionTests { From 6b9e653618c5fc7a66a05ff702ecc32803156647 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Tue, 27 May 2025 17:05:29 +0200 Subject: [PATCH 02/20] Fix runtime hints for native images. (#3806) Signed-off-by: Olga Maciaszek-Sharma --- .../GatewayServerMvcAutoConfiguration.java | 9 +- .../GatewayMvcAotRuntimeHintsRegistrar.java | 83 ------------ .../GatewayMvcRuntimeHintsProcessor.java | 124 ++++++++++++++++++ 3 files changed, 130 insertions(+), 86 deletions(-) delete mode 100644 spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java create mode 100644 spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java index 2aecabe1..cc69fd06 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java @@ -32,9 +32,9 @@ import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.http.client.HttpRedirects; import org.springframework.boot.web.client.RestClientCustomizer; import org.springframework.cloud.gateway.server.mvc.common.ArgumentSupplierBeanPostProcessor; -import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcAotRuntimeHintsRegistrar; import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcPropertiesBeanDefinitionRegistrar; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcRuntimeHintsProcessor; import org.springframework.cloud.gateway.server.mvc.config.RouterFunctionHolderFactory; import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; import org.springframework.cloud.gateway.server.mvc.filter.FilterBeanFactoryDiscoverer; @@ -60,7 +60,6 @@ import org.springframework.cloud.gateway.server.mvc.predicate.PredicateDiscovere import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; @@ -80,7 +79,6 @@ import org.springframework.web.client.RestClient; PredicateAutoConfiguration.class }) @ConditionalOnProperty(name = GatewayMvcProperties.PREFIX + ".enabled", matchIfMissing = true) @Import(GatewayMvcPropertiesBeanDefinitionRegistrar.class) -@ImportRuntimeHints(GatewayMvcAotRuntimeHintsRegistrar.class) public class GatewayServerMvcAutoConfiguration { @Bean @@ -209,6 +207,11 @@ public class GatewayServerMvcAutoConfiguration { return new XForwardedRequestHeadersFilterProperties(); } + @Bean + static GatewayMvcRuntimeHintsProcessor gatewayMvcRuntimeHintsProcessor() { + return new GatewayMvcRuntimeHintsProcessor(); + } + static class GatewayHttpClientEnvironmentPostProcessor implements EnvironmentPostProcessor { static final boolean APACHE = ClassUtils.isPresent("org.apache.hc.client5.http.impl.classic.HttpClients", null); diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java deleted file mode 100644 index c171c240..00000000 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2013-2024 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.server.mvc.config; - -import java.util.Arrays; -import java.util.Set; - -import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.ReflectionHints; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; -import org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.BodyFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; -import org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.TokenRelayFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions; -import org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions; -import org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates; -import org.springframework.lang.NonNull; -import org.springframework.util.ClassUtils; - -/** - * AOT runtime hints registrar on the gateway server mvc. - * - * @author Jürgen Wißkirchen - */ -public class GatewayMvcAotRuntimeHintsRegistrar implements RuntimeHintsRegistrar { - - // TODO: fix AOT HINTS - private static final Set> FUNCTION_PROVIDERS = Set.of(HandlerFunctions.class, - FilterAutoConfiguration.LoadBalancerHandlerConfiguration.class, FilterFunctions.class, - BeforeFilterFunctions.class, AfterFilterFunctions.class, TokenRelayFilterFunctions.class, - BodyFilterFunctions.class, CircuitBreakerFilterFunctions.class, GatewayRouterFunctions.class, - LoadBalancerFilterFunctions.class, GatewayRequestPredicates.class, Bucket4jFilterFunctions.class); - - private static final Set> PROPERTIES = Set.of(FilterProperties.class, PredicateProperties.class, - RouteProperties.class); - - @Override - public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) { - final ReflectionHints reflectionHints = hints.reflection(); - FUNCTION_PROVIDERS.forEach(clazz -> addHintsForClass(reflectionHints, clazz, classLoader)); - - PROPERTIES.forEach(clazz -> reflectionHints.registerType(clazz, MemberCategory.PUBLIC_FIELDS, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS)); - } - - /** - * Add hints for the given class. Since we need to register mostly static methods, the - * annotation way with @Reflective does not work here. - * @param reflectionHints the reflection hints - * @param clazz the class to add hints for - * @param classLoader the class loader - */ - private void addHintsForClass(ReflectionHints reflectionHints, Class clazz, ClassLoader classLoader) { - if (!ClassUtils.isPresent(clazz.getName(), classLoader)) { - return; // safety net - } - Arrays.stream(clazz.getMethods()) - .forEach(method -> reflectionHints.registerMethod(method, ExecutableMode.INVOKE)); - } - -} diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java new file mode 100644 index 00000000..4691a19f --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java @@ -0,0 +1,124 @@ +/* + * 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.server.mvc.config; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; +import org.springframework.cloud.gateway.server.mvc.predicate.PredicateAutoConfiguration; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AssignableTypeFilter; + +/** + * A {@link BeanFactoryInitializationAotProcessor} responsible for registering reflection + * hints for Gateway MVC beans. + * + * @author Jürgen Wißkirchen + * @author Olga Maciaszek-Sharma + * @since 4.3.0 + */ +public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializationAotProcessor { + + private static final Log LOG = LogFactory.getLog(GatewayMvcRuntimeHintsProcessor.class); + + private static final String GATEWAY_MVC_FILTER_PACKAGE_NAME = "org.springframework.cloud.gateway.server.mvc.filter"; + + private static final String GATEWAY_MVC_PREDICATE_PACKAGE_NAME = "org.springframework.cloud.gateway.server.mvc.predicate"; + + private static final Map> beansConditionalOnClasses = Map.of( + "io.github.bucket4j.BucketConfiguration", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions"), + "org.springframework.cloud.client.circuitbreaker.CircuitBreaker", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions"), + "org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions"), + "org.springframework.retry.support.RetryTemplate", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.RetryFilterFunctions"), + "org.springframework.security.oauth2.client.OAuth2AuthorizedClient", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.TokenRelayFilterFunctions")); + + private static final Set> PROPERTIES = Set.of(FilterProperties.class, PredicateProperties.class, + RouteProperties.class); + + @Override + public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { + return (generationContext, beanFactoryInitializationCode) -> { + ReflectionHints hints = generationContext.getRuntimeHints().reflection(); + Set> typesToRegister = Stream + .of(getTypesToRegister(GATEWAY_MVC_FILTER_PACKAGE_NAME), + getTypesToRegister(GATEWAY_MVC_PREDICATE_PACKAGE_NAME), PROPERTIES) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + typesToRegister.forEach(clazz -> hints.registerType(TypeReference.of(clazz), + hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))); + }; + } + + private static Set> getTypesToRegister(String packageName) { + Set> classesToAdd = new HashSet<>(); + ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + provider.addIncludeFilter(new AssignableTypeFilter(Object.class)); + provider.addExcludeFilter(new AssignableTypeFilter(FilterAutoConfiguration.class)); + provider.addExcludeFilter(new AssignableTypeFilter(PredicateAutoConfiguration.class)); + Set components = provider.findCandidateComponents(packageName); + for (BeanDefinition component : components) { + Class clazz; + try { + clazz = Class.forName(component.getBeanClassName()); + if (shouldRegisterClass(clazz)) { + classesToAdd.add(clazz); + } + } + catch (NoClassDefFoundError | ClassNotFoundException exception) { + if (LOG.isDebugEnabled()) { + LOG.debug(exception); + } + } + } + return classesToAdd; + } + + private static boolean shouldRegisterClass(Class clazz) { + Set conditionClasses = beansConditionalOnClasses.getOrDefault(clazz.getName(), Collections.emptySet()); + for (String conditionClass : conditionClasses) { + try { + GatewayMvcRuntimeHintsProcessor.class.getClassLoader().loadClass(conditionClass); + } + catch (ClassNotFoundException e) { + return false; + } + } + return true; + } + +} From 86b4529ab6da946c8b5ea000b8958c544289ee6d Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 27 May 2025 18:24:25 +0200 Subject: [PATCH 03/20] Add documentation for routing to functions (#3767) * Add documentation for routing to functions This one specifically refers to using Spring Cloud Function framework Signed-off-by: Oleg Zhurakousky * Update java-routes-api.adoc Signed-off-by: Spencer Gibb --------- Signed-off-by: Oleg Zhurakousky Signed-off-by: Spencer Gibb Co-authored-by: Spencer Gibb --- .../java-routes-api.adoc | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/java-routes-api.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/java-routes-api.adoc index f653d36e..a8a7efba 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/java-routes-api.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/java-routes-api.adoc @@ -49,6 +49,71 @@ class SimpleGateway { [[gateway-handlerfunctions]] == Gateway MVC Handler Functions -Various `RouterFunctions.Builder` methods require a `HandlerFunction`. To create a route that is proxied by the MVC Gateway, `HandlerFunction` implementations are supplied in `org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions`. The most basic is the `http()` `HandlerFunction`. The function looks for a `URI` in the `org.springframework.cloud.gateway.server.mvc.common.MvcUtils.GATEWAY_REQUEST_URL_ATTR` request attribute. This allows for dynamic targets such as load balancing to set the `URI`. -WARNING: As of version 4.1.7, `HandlerFunctions.http(String)` and `HandlerFunctions.http(URI)` are now deprecated. Please use `HandlerFunctions.http()` in combination with the `BeforeFilterFunctions.uri()` filter instead. This fixes inconsistencies in dealing with the route url request attribute. \ No newline at end of file +Various `RouterFunctions.Builder` methods require a `HandlerFunction`. To create a route that is proxied by the MVC Gateway, `HandlerFunction` implementations are supplied in `org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions`. + +=== HTTP Handler Function +The most basic handler function is `http()` `HandlerFunction`. If a `URI` is supplied as a parameter, that is the `URI` used as the downstream target for sending the HTTP requests (as seen in the example above). If no parameter is passed, the function looks for a `URI` in the `org.springframework.cloud.gateway.server.mvc.common.MvcUtils.GATEWAY_REQUEST_URL_ATTR` request attribute. This allows for dynamic targets such as load balancing to set the `URI`. + + +WARNING: As of version 4.1.7, `HandlerFunctions.http(String)` and `HandlerFunctions.http(URI)` are now deprecated. Please use `HandlerFunctions.http()` in combination with the `BeforeFilterFunctions.uri()` filter instead. This fixes inconsistencies in dealing with the route url request attribute. + +=== Spring Cloud Function Handler Function +By placing https://spring.io/projects/spring-cloud-function[Spring Cloud Function] on the classpath, Spring Cloud Gateway will automatically configure routes to invoke functions you define as beans. The bean names of the functions will be used as the path of the routes. + +For example, given the following configuration: + +[source,xml] +---- + + org.springframework.cloud + spring-cloud-function-context + +---- + +Once Spring Cloud Function dependency is provided the name of the Java function bean becomes the path you can use to route to functions. + +For example, assume the following application: + +[source,java] +---- +@SpringBootApplication +public class DemoFunctionGatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoFunctionGatewayApplication.class, args); + } + + + @Bean + public Function uppercase() { + return v -> v.toUpperCase(); + } + + @Bean + public Function concat() { + return v -> v + v; + } +} +---- +You can invoke the `concat` or `uppercase` functions by issuing a `GET` or `POST` request to `/concat` or `/uppercase`. + +Making a `GET` request to ``http://localhost:8080/uppercase/hello` will invoke the `uppercase` function with the String `hello` and return `HELLO` in the `GET` response body. + +Instead of passing the function parameter as a path parameter you can use a `POST` request. For example the following cURL command can issued to invoke the `concat` function: + +[source,bash] +---- +$ curl -d ‘"hello"' -H "Content-Type: application/json" -X POST http://localhost:8080/concat +---- + +The response body will contain `hellohello`. + +Spring Cloud Gateway also supports function composition by issuing a request to a path composed of function names separated by a comma. For example: + +[source,bash] +---- +$ curl -d ‘"hello"' -H "Content-Type: application/json" -X POST http://localhost:8080/concat,uppercase +---- + +The response body will contain `HELLOHELLO`. From d349a9f4cfdf96846ac7b4d301e610df2f3e55e0 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Tue, 27 May 2025 17:05:29 +0200 Subject: [PATCH 04/20] Fix runtime hints for native images. (#3806) Signed-off-by: Olga Maciaszek-Sharma # Conflicts: # spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java # spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java --- .../GatewayServerMvcAutoConfiguration.java | 9 +- .../GatewayMvcAotRuntimeHintsRegistrar.java | 82 ------------ .../GatewayMvcRuntimeHintsProcessor.java | 120 ++++++++++++++++++ 3 files changed, 126 insertions(+), 85 deletions(-) delete mode 100644 spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java create mode 100644 spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java index 9baad4ce..b6807943 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java @@ -28,9 +28,9 @@ import org.springframework.boot.web.client.ClientHttpRequestFactories; import org.springframework.boot.web.client.ClientHttpRequestFactorySettings; import org.springframework.boot.web.client.RestClientCustomizer; import org.springframework.cloud.gateway.server.mvc.common.ArgumentSupplierBeanPostProcessor; -import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcAotRuntimeHintsRegistrar; import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcPropertiesBeanDefinitionRegistrar; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcRuntimeHintsProcessor; import org.springframework.cloud.gateway.server.mvc.config.RouterFunctionHolderFactory; import org.springframework.cloud.gateway.server.mvc.filter.FormFilter; import org.springframework.cloud.gateway.server.mvc.filter.ForwardedRequestHeadersFilter; @@ -51,7 +51,6 @@ import org.springframework.cloud.gateway.server.mvc.predicate.PredicateDiscovere import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.core.env.Environment; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.JdkClientHttpRequestFactory; @@ -67,7 +66,6 @@ import org.springframework.web.client.RestClient; @AutoConfiguration(after = { RestTemplateAutoConfiguration.class, RestClientAutoConfiguration.class }) @ConditionalOnProperty(name = "spring.cloud.gateway.mvc.enabled", matchIfMissing = true) @Import(GatewayMvcPropertiesBeanDefinitionRegistrar.class) -@ImportRuntimeHints(GatewayMvcAotRuntimeHintsRegistrar.class) public class GatewayServerMvcAutoConfiguration { @Bean @@ -219,4 +217,9 @@ public class GatewayServerMvcAutoConfiguration { return new XForwardedRequestHeadersFilterProperties(); } + @Bean + static GatewayMvcRuntimeHintsProcessor gatewayMvcRuntimeHintsProcessor() { + return new GatewayMvcRuntimeHintsProcessor(); + } + } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java deleted file mode 100644 index e4482d3a..00000000 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcAotRuntimeHintsRegistrar.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2013-2024 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.server.mvc.config; - -import java.util.Arrays; -import java.util.Set; - -import org.springframework.aot.hint.ExecutableMode; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.ReflectionHints; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; -import org.springframework.cloud.gateway.server.mvc.filter.AfterFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.BodyFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerHandlerSupplier; -import org.springframework.cloud.gateway.server.mvc.filter.TokenRelayFilterFunctions; -import org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions; -import org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions; -import org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates; -import org.springframework.lang.NonNull; -import org.springframework.util.ClassUtils; - -/** - * AOT runtime hints registrar on the gateway server mvc. - * - * @author Jürgen Wißkirchen - */ -public class GatewayMvcAotRuntimeHintsRegistrar implements RuntimeHintsRegistrar { - - private static final Set> FUNCTION_PROVIDERS = Set.of(HandlerFunctions.class, - LoadBalancerHandlerSupplier.class, FilterFunctions.class, BeforeFilterFunctions.class, - AfterFilterFunctions.class, TokenRelayFilterFunctions.class, BodyFilterFunctions.class, - CircuitBreakerFilterFunctions.class, GatewayRouterFunctions.class, LoadBalancerFilterFunctions.class, - GatewayRequestPredicates.class, Bucket4jFilterFunctions.class); - - private static final Set> PROPERTIES = Set.of(FilterProperties.class, PredicateProperties.class, - RouteProperties.class); - - @Override - public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) { - final ReflectionHints reflectionHints = hints.reflection(); - FUNCTION_PROVIDERS.forEach(clazz -> addHintsForClass(reflectionHints, clazz, classLoader)); - - PROPERTIES.forEach(clazz -> reflectionHints.registerType(clazz, MemberCategory.PUBLIC_FIELDS, - MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS)); - } - - /** - * Add hints for the given class. Since we need to register mostly static methods, the - * annotation way with @Reflective does not work here. - * @param reflectionHints the reflection hints - * @param clazz the class to add hints for - * @param classLoader the class loader - */ - private void addHintsForClass(ReflectionHints reflectionHints, Class clazz, ClassLoader classLoader) { - if (!ClassUtils.isPresent(clazz.getName(), classLoader)) { - return; // safety net - } - Arrays.stream(clazz.getMethods()) - .forEach(method -> reflectionHints.registerMethod(method, ExecutableMode.INVOKE)); - } - -} diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java new file mode 100644 index 00000000..fb78da79 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java @@ -0,0 +1,120 @@ +/* + * 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.server.mvc.config; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.ReflectionHints; +import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; +import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AssignableTypeFilter; + +/** + * A {@link BeanFactoryInitializationAotProcessor} responsible for registering reflection + * hints for Gateway MVC beans. + * + * @author Jürgen Wißkirchen + * @author Olga Maciaszek-Sharma + * @since 4.3.0 + */ +public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializationAotProcessor { + + private static final Log LOG = LogFactory.getLog(GatewayMvcRuntimeHintsProcessor.class); + + private static final String GATEWAY_MVC_FILTER_PACKAGE_NAME = "org.springframework.cloud.gateway.server.mvc.filter"; + + private static final String GATEWAY_MVC_PREDICATE_PACKAGE_NAME = "org.springframework.cloud.gateway.server.mvc.predicate"; + + private static final Map> beansConditionalOnClasses = Map.of( + "io.github.bucket4j.BucketConfiguration", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions"), + "org.springframework.cloud.client.circuitbreaker.CircuitBreaker", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions"), + "org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions"), + "org.springframework.retry.support.RetryTemplate", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.RetryFilterFunctions"), + "org.springframework.security.oauth2.client.OAuth2AuthorizedClient", + Set.of("org.springframework.cloud.gateway.server.mvc.filter.TokenRelayFilterFunctions")); + + private static final Set> PROPERTIES = Set.of(FilterProperties.class, PredicateProperties.class, + RouteProperties.class); + + @Override + public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { + return (generationContext, beanFactoryInitializationCode) -> { + ReflectionHints hints = generationContext.getRuntimeHints().reflection(); + Set> typesToRegister = Stream + .of(getTypesToRegister(GATEWAY_MVC_FILTER_PACKAGE_NAME), + getTypesToRegister(GATEWAY_MVC_PREDICATE_PACKAGE_NAME), PROPERTIES) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + typesToRegister.forEach(clazz -> hints.registerType(TypeReference.of(clazz), + hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))); + }; + } + + private static Set> getTypesToRegister(String packageName) { + Set> classesToAdd = new HashSet<>(); + ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + provider.addIncludeFilter(new AssignableTypeFilter(Object.class)); + Set components = provider.findCandidateComponents(packageName); + for (BeanDefinition component : components) { + Class clazz; + try { + clazz = Class.forName(component.getBeanClassName()); + if (shouldRegisterClass(clazz)) { + classesToAdd.add(clazz); + } + } + catch (NoClassDefFoundError | ClassNotFoundException exception) { + if (LOG.isDebugEnabled()) { + LOG.debug(exception); + } + } + } + return classesToAdd; + } + + private static boolean shouldRegisterClass(Class clazz) { + Set conditionClasses = beansConditionalOnClasses.getOrDefault(clazz.getName(), Collections.emptySet()); + for (String conditionClass : conditionClasses) { + try { + GatewayMvcRuntimeHintsProcessor.class.getClassLoader().loadClass(conditionClass); + } + catch (ClassNotFoundException e) { + return false; + } + } + return true; + } + +} From 738f2e8f7257d4989910f2f7d925d22bd1ed47e9 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Wed, 28 May 2025 16:54:12 +0200 Subject: [PATCH 05/20] Include interfaces for runtime hints scan. Signed-off-by: Olga Maciaszek-Sharma --- .../config/GatewayMvcRuntimeHintsProcessor.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java index fb78da79..b133a5cc 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java @@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; @@ -84,7 +85,7 @@ public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializatio private static Set> getTypesToRegister(String packageName) { Set> classesToAdd = new HashSet<>(); - ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); + ClassPathScanningCandidateComponentProvider provider = buildProvider(); provider.addIncludeFilter(new AssignableTypeFilter(Object.class)); Set components = provider.findCandidateComponents(packageName); for (BeanDefinition component : components) { @@ -104,6 +105,17 @@ public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializatio return classesToAdd; } + private static ClassPathScanningCandidateComponentProvider buildProvider() { + return new ClassPathScanningCandidateComponentProvider(false) { + @SuppressWarnings("NullableProblems") + @Override + protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { + // Include both concrete classes and interfaces + return beanDefinition.getMetadata().isIndependent() && !beanDefinition.getMetadata().isAnnotation(); + } + }; + } + private static boolean shouldRegisterClass(Class clazz) { Set conditionClasses = beansConditionalOnClasses.getOrDefault(clazz.getName(), Collections.emptySet()); for (String conditionClass : conditionClasses) { From 33ea007a6baa3d9b79f94a9932cd6fe3ecf0cae9 Mon Sep 17 00:00:00 2001 From: sgibb Date: Thu, 18 Apr 2024 11:52:24 -0400 Subject: [PATCH 06/20] Adds support for trusted-proxies property. spring.cloud.gateway.trusted-proxies and spring.cloud.gateway.mvc.trusted-proxies --- docs/modules/ROOT/nav.adoc | 1 + .../httpheadersfilters.adoc | 45 +++++ .../httpheadersfilters.adoc | 4 +- .../GatewayServerMvcAutoConfiguration.java | 16 +- .../mvc/config/GatewayMvcProperties.java | 15 ++ .../filter/ForwardedRequestHeadersFilter.java | 43 ++++- .../server/mvc/filter/TrustedProxies.java | 120 +++++++++++++ .../XForwardedRequestHeadersFilter.java | 75 ++++++-- .../server/mvc/ServerMvcIntegrationTests.java | 2 +- .../ForwardedRequestHeadersFilterTests.java | 102 +++++++++-- .../XForwardedRequestHeadersFilterTests.java | 162 ++++++++++++++++++ .../gateway/server/mvc/test/TestUtils.java | 6 +- .../src/test/resources/application.yml | 6 +- ...efaultNettyHttpForwardedHeaderHandler.java | 137 +++++++++++++++ .../config/GatewayAutoConfiguration.java | 31 +++- .../gateway/config/GatewayProperties.java | 15 ++ .../headers/ForwardedHeadersFilter.java | 52 +++++- .../filter/headers/TrustedProxies.java | 114 ++++++++++++ .../headers/XForwardedHeadersFilter.java | 66 +++++-- .../config/GatewayAutoConfigurationTests.java | 44 ++++- ...yGatewayFilterFactoryIntegrationTests.java | 3 +- .../headers/ForwardedHeadersFilterTests.java | 129 ++++++++++++-- .../headers/XForwardedHeadersFilterTests.java | 119 +++++++++++-- .../gateway/test/GatewayIntegrationTests.java | 5 +- .../resources/application-remote-address.yml | 1 + 25 files changed, 1193 insertions(+), 120 deletions(-) create mode 100644 docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/httpheadersfilters.adoc create mode 100644 spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/TrustedProxies.java create mode 100644 spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java create mode 100644 spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/DefaultNettyHttpForwardedHeaderHandler.java create mode 100644 spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index edcb0484..fdccafb9 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -109,6 +109,7 @@ *** xref:spring-cloud-gateway-server-mvc/filters/requestsize.adoc[] *** xref:spring-cloud-gateway-server-mvc/filters/setrequesthostheader.adoc[] *** xref:spring-cloud-gateway-server-mvc/filters/tokenrelay.adoc[] +** xref:spring-cloud-gateway-server-mvc/httpheadersfilters.adoc[] ** xref:spring-cloud-gateway-server-mvc/writing-custom-predicates-and-filters.adoc[] ** xref:spring-cloud-gateway-server-mvc/working-with-servlets-and-filters.adoc[] diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/httpheadersfilters.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/httpheadersfilters.adoc new file mode 100644 index 00000000..d60c00d7 --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/httpheadersfilters.adoc @@ -0,0 +1,45 @@ +[[httpheadersfilters]] += HttpHeadersFilters + +HttpHeadersFilters are applied to the requests before sending them downstream, such as in the `NettyRoutingFilter`. + +[[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. + +[[removehopbyhop-headers-filter]] +== RemoveHopByHop Headers Filter +The `RemoveHopByHop` Headers Filter removes headers from forwarded requests. The default list of headers that is removed comes from the https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-14#section-7.1.3[IETF]. + +.The default removed headers are: +* Connection +* Keep-Alive +* Proxy-Authenticate +* Proxy-Authorization +* TE +* Trailer +* 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. + +[[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. + +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` + +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` + diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway/httpheadersfilters.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway/httpheadersfilters.adoc index e2a6ac82..d73d0445 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway/httpheadersfilters.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway/httpheadersfilters.adoc @@ -5,7 +5,7 @@ [[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. +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. [[removehopbyhop-headers-filter]] == RemoveHopByHop Headers Filter @@ -25,7 +25,7 @@ To change this, set the `spring.cloud.gateway.filter.remove-hop-by-hop.headers` [[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. +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. Creating of individual headers can be controlled by the following boolean properties (defaults to true): diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java index b6807943..31d0a727 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfiguration.java @@ -41,6 +41,7 @@ import org.springframework.cloud.gateway.server.mvc.filter.RemoveHopByHopRequest import org.springframework.cloud.gateway.server.mvc.filter.RemoveHopByHopResponseHeadersFilter; import org.springframework.cloud.gateway.server.mvc.filter.RemoveHttp2StatusResponseHeadersFilter; import org.springframework.cloud.gateway.server.mvc.filter.TransferEncodingNormalizationRequestHeadersFilter; +import org.springframework.cloud.gateway.server.mvc.filter.TrustedProxies; import org.springframework.cloud.gateway.server.mvc.filter.WeightCalculatorFilter; import org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter; import org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilterProperties; @@ -50,6 +51,7 @@ import org.springframework.cloud.gateway.server.mvc.handler.RestClientProxyExcha import org.springframework.cloud.gateway.server.mvc.predicate.PredicateDiscoverer; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Import; import org.springframework.core.env.Environment; import org.springframework.http.client.ClientHttpRequestFactory; @@ -100,10 +102,9 @@ public class GatewayServerMvcAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = GatewayMvcProperties.PREFIX, name = "forwarded-request-headers-filter.enabled", - matchIfMissing = true) - public ForwardedRequestHeadersFilter forwardedRequestHeadersFilter() { - return new ForwardedRequestHeadersFilter(); + @Conditional(TrustedProxies.ForwardedTrustedProxiesCondition.class) + public ForwardedRequestHeadersFilter forwardedRequestHeadersFilter(GatewayMvcProperties properties) { + return new ForwardedRequestHeadersFilter(properties.getTrustedProxies()); } @Bean @@ -207,9 +208,10 @@ public class GatewayServerMvcAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = XForwardedRequestHeadersFilterProperties.PREFIX, name = ".enabled", matchIfMissing = true) - public XForwardedRequestHeadersFilter xForwardedRequestHeadersFilter( - XForwardedRequestHeadersFilterProperties props) { - return new XForwardedRequestHeadersFilter(props); + @Conditional(TrustedProxies.XForwardedTrustedProxiesCondition.class) + public XForwardedRequestHeadersFilter xForwardedRequestHeadersFilter(XForwardedRequestHeadersFilterProperties props, + GatewayMvcProperties gatewayMvcProperties) { + return new XForwardedRequestHeadersFilter(props, gatewayMvcProperties.getTrustedProxies()); } @Bean diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcProperties.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcProperties.java index ac553b7d..3c4c2494 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcProperties.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcProperties.java @@ -65,6 +65,12 @@ public class GatewayMvcProperties { */ private int streamingBufferSize = 16384; + /** + * Regular expression defining proxies that are trusted when they appear in a + * Forwarded of X-Forwarded header. + */ + private String trustedProxies; + public List getRoutes() { return routes; } @@ -101,6 +107,14 @@ public class GatewayMvcProperties { this.streamingBufferSize = streamingBufferSize; } + public String getTrustedProxies() { + return trustedProxies; + } + + public void setTrustedProxies(String trustedProxies) { + this.trustedProxies = trustedProxies; + } + @Override public String toString() { return new ToStringCreator(this).append("httpClient", httpClient) @@ -108,6 +122,7 @@ public class GatewayMvcProperties { .append("routesMap", routesMap) .append("streamingMediaTypes", streamingMediaTypes) .append("streamingBufferSize", streamingBufferSize) + .append("trustedProxies", trustedProxies) .toString(); } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilter.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilter.java index e4fedaf9..bb085b1f 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilter.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/ForwardedRequestHeadersFilter.java @@ -24,7 +24,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.core.Ordered; +import org.springframework.core.log.LogMessage; import org.springframework.http.HttpHeaders; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedCaseInsensitiveMap; @@ -34,11 +39,26 @@ import org.springframework.web.servlet.function.ServerRequest; public class ForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestHttpHeadersFilter, Ordered { + private static final Log log = LogFactory.getLog(ForwardedRequestHeadersFilter.class); + /** * Forwarded header. */ public static final String FORWARDED_HEADER = "Forwarded"; + private final TrustedProxies trustedProxies; + + @Deprecated + public ForwardedRequestHeadersFilter() { + trustedProxies = s -> true; + log.warn(GatewayMvcProperties.PREFIX + + ".trusted-proxies is not set. Using deprecated Constructor. Untrusted hosts might be added to Forwarded header."); + } + + public ForwardedRequestHeadersFilter(String trustedProxiesRegex) { + trustedProxies = TrustedProxies.from(trustedProxiesRegex); + } + /* for testing */ static List parse(List values) { ArrayList forwardeds = new ArrayList<>(); @@ -46,8 +66,11 @@ public class ForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestH return forwardeds; } for (String value : values) { - Forwarded forwarded = parse(value); - forwardeds.add(forwarded); + String[] forwardedValues = StringUtils.tokenizeToStringArray(value, ","); + for (String forwardedValue : forwardedValues) { + Forwarded forwarded = parse(forwardedValue); + forwardeds.add(forwarded); + } } return forwardeds; } @@ -89,6 +112,13 @@ public class ForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestH @Override public HttpHeaders apply(HttpHeaders input, ServerRequest request) { + if (request.servletRequest().getRemoteAddr() != null + && !trustedProxies.isTrusted(request.servletRequest().getRemoteAddr())) { + log.trace(LogMessage.format("Remote address not trusted. pattern %s remote address %s", trustedProxies, + request.servletRequest().getRemoteHost())); + return input; + } + HttpHeaders original = input; HttpHeaders updated = new HttpHeaders(); @@ -102,7 +132,10 @@ public class ForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestH List forwardeds = parse(original.get(FORWARDED_HEADER)); for (Forwarded f : forwardeds) { - updated.add(FORWARDED_HEADER, f.toHeaderValue()); + // only add if "for" value matches trustedProxies + if (trustedProxies.isTrusted(f.get("for"))) { + updated.add(FORWARDED_HEADER, f.toHeaderValue()); + } } // TODO: add new forwarded @@ -124,6 +157,10 @@ public class ForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestH forValue = "[" + forValue + "]"; } } + if (!trustedProxies.isTrusted(forValue)) { + // don't add for value + return; + } int port = remoteAddress.getPort(); if (port >= 0) { forValue = forValue + ":" + port; diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/TrustedProxies.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/TrustedProxies.java new file mode 100644 index 00000000..2489f50d --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/TrustedProxies.java @@ -0,0 +1,120 @@ +/* + * 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.server.mvc.filter; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +import org.springframework.boot.autoconfigure.condition.AllNestedConditions; +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +@FunctionalInterface +public interface TrustedProxies { + + boolean isTrusted(String host); + + static TrustedProxies from(@NonNull String trustedProxies) { + Assert.hasText(trustedProxies, "trustedProxies must not be empty"); + Pattern pattern = Pattern.compile(trustedProxies); + return value -> pattern.matcher(value).matches(); + } + + class ForwardedTrustedProxiesCondition extends AllNestedConditions { + + public ForwardedTrustedProxiesCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnProperty(name = GatewayMvcProperties.PREFIX + ".forwarded-request-headers-filter.enabled", + matchIfMissing = true) + static class OnPropertyEnabled { + + } + + @ConditionalOnPropertyExists(GatewayMvcProperties.PREFIX + ".trusted-proxies") + static class OnTrustedProxiesNotEmpty { + + } + + } + + class XForwardedTrustedProxiesCondition extends AllNestedConditions { + + public XForwardedTrustedProxiesCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnProperty(name = XForwardedRequestHeadersFilterProperties.PREFIX + ".enabled", + matchIfMissing = true) + static class OnPropertyEnabled { + + } + + @ConditionalOnPropertyExists(GatewayMvcProperties.PREFIX + ".trusted-proxies") + static class OnTrustedProxiesNotEmpty { + + } + + } + + class OnPropertyExistsCondition extends SpringBootCondition { + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + try { + String value = metadata.getAnnotations().get(ConditionalOnPropertyExists.class).getString("value"); + String property = context.getEnvironment().getProperty(value); + if (!StringUtils.hasText(property)) { + return ConditionOutcome.noMatch(value + " property is not set or is empty."); + } + return ConditionOutcome.match(value + " property is not empty."); + } + catch (NoSuchElementException e) { + return ConditionOutcome.noMatch("Missing required property 'value' of @ConditionalOnPropertyExists"); + } + } + + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.TYPE, ElementType.METHOD }) + @Documented + @Conditional(OnPropertyExistsCondition.class) + @interface ConditionalOnPropertyExists { + + /** + * @return the property + */ + String value(); + + } + +} 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 bee93756..e8b556c6 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 @@ -16,18 +16,24 @@ package org.springframework.cloud.gateway.server.mvc.filter; -import java.net.InetSocketAddress; import java.net.URI; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.function.Predicate; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.cloud.gateway.server.mvc.common.MvcUtils; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.core.Ordered; +import org.springframework.core.log.LogMessage; import org.springframework.http.HttpHeaders; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.servlet.function.ServerRequest; @@ -37,6 +43,8 @@ import static org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequ @ConfigurationProperties("spring.cloud.gateway.x-forwarded") public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.RequestHttpHeadersFilter, Ordered { + private static final Log log = LogFactory.getLog(XForwardedRequestHeadersFilter.class); + /** Default http port. */ public static final int HTTP_PORT = 80; @@ -100,12 +108,30 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request /** If appending X-Forwarded-Prefix as a list is enabled. */ private boolean prefixAppend = true; + private final TrustedProxies trustedProxies; + @Deprecated public XForwardedRequestHeadersFilter() { - this(new XForwardedRequestHeadersFilterProperties()); + this(new XForwardedRequestHeadersFilterProperties(), s -> true); + log.warn(GatewayMvcProperties.PREFIX + + ".trusted-proxies is not set. Using deprecated Constructor. Untrusted hosts might be added to X-Forwarded header."); } + @Deprecated public XForwardedRequestHeadersFilter(XForwardedRequestHeadersFilterProperties props) { + this(props, s -> true); + log.warn(GatewayMvcProperties.PREFIX + + ".trusted-proxies is not set. Using deprecated Constructor. Untrusted hosts might be added to X-Forwarded header."); + } + + public XForwardedRequestHeadersFilter(XForwardedRequestHeadersFilterProperties props, String trustedProxies) { + this(props, TrustedProxies.from(trustedProxies)); + } + + private XForwardedRequestHeadersFilter(XForwardedRequestHeadersFilterProperties props, + TrustedProxies trustedProxies) { + Assert.notNull(trustedProxies, "trustedProxies must not be null"); + // TODO: remove individual properties in 4.2.0 // this.properties = properties; PropertyMapper map = PropertyMapper.get(); @@ -121,6 +147,8 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request map.from(props::isPortAppend).to(b -> this.portAppend = b); map.from(props::isProtoAppend).to(b -> this.protoAppend = b); map.from(props::isPrefixAppend).to(b -> this.prefixAppend = b); + + this.trustedProxies = trustedProxies; } @DeprecatedConfigurationProperty(replacement = PREFIX + ".order") @@ -372,6 +400,13 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request @Override public HttpHeaders apply(HttpHeaders input, ServerRequest request) { + if (request.servletRequest().getRemoteAddr() != null + && !trustedProxies.isTrusted(request.servletRequest().getRemoteAddr())) { + log.trace(LogMessage.format("Remote address not trusted. pattern %s remote address %s", trustedProxies, + request.servletRequest().getRemoteHost())); + return input; + } + HttpHeaders original = input; HttpHeaders updated = new HttpHeaders(); @@ -379,10 +414,12 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request updated.addAll(entry.getKey(), entry.getValue()); } - InetSocketAddress remoteAddress = request.remoteAddress().orElse(null); - if (isForEnabled() && remoteAddress != null && remoteAddress.getAddress() != null) { - String remoteAddr = remoteAddress.getAddress().getHostAddress(); - write(updated, X_FORWARDED_FOR_HEADER, remoteAddr, isForAppend()); + if (isForEnabled()) { + String remoteAddr = null; + if (request.servletRequest().getRemoteAddr() != null) { + remoteAddr = request.servletRequest().getRemoteAddr(); + } + write(updated, X_FORWARDED_FOR_HEADER, remoteAddr, isForAppend(), trustedProxies::isTrusted); } String proto = request.uri().getScheme(); @@ -457,17 +494,22 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request } private void write(HttpHeaders headers, String name, String value, boolean append) { - if (value == null) { - return; - } + write(headers, name, value, append, s -> true); + } + + private void write(HttpHeaders headers, String name, String value, boolean append, Predicate shouldWrite) { if (append) { - headers.add(name, value); + if (value != null) { + headers.add(name, value); + } // these headers should be treated as a single comma separated header - List values = headers.get(name); - String delimitedValue = StringUtils.collectionToCommaDelimitedString(values); - headers.set(name, delimitedValue); + if (headers.containsKey(name)) { + List values = headers.get(name).stream().filter(shouldWrite).toList(); + String delimitedValue = StringUtils.collectionToCommaDelimitedString(values); + headers.set(name, delimitedValue); + } } - else { + else if (value != null && shouldWrite.test(value)) { headers.set(name, value); } } @@ -476,11 +518,6 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request return HTTPS_SCHEME.equals(scheme) ? HTTPS_PORT : HTTP_PORT; } - private boolean hasHeader(ServerRequest request, String name) { - HttpHeaders headers = request.headers().asHttpHeaders(); - return headers.containsKey(name) && StringUtils.hasLength(headers.getFirst(name)); - } - private String toHostHeader(ServerRequest request) { int port = request.uri().getPort(); String host = request.uri().getHost(); diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java index aaf409af..20f1408e 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java @@ -584,7 +584,7 @@ public class ServerMvcIntegrationTests { .isOk(); } - public static final MediaType FORM_URL_ENCODED_CONTENT_TYPE = new MediaType(APPLICATION_FORM_URLENCODED, + private static final MediaType FORM_URL_ENCODED_CONTENT_TYPE = new MediaType(APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8); @Test 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 4da36cdc..b5174e55 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 @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import org.junit.jupiter.api.Test; @@ -61,7 +62,7 @@ public class ForwardedRequestHeadersFilterTests { servletRequest.setRemoteHost("10.0.0.1"); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); - ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(); + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(".*"); HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); @@ -81,28 +82,39 @@ public class ForwardedRequestHeadersFilterTests { public void forwardedHeaderExists() { MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") .remoteAddress("10.0.0.1:80") - .header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https; for=23.45.67.89") + .header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https, for=23.45.67.89") .buildRequest(null); servletRequest.setRemoteHost("10.0.0.1"); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); - ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(); + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(".*"); HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); - assertThat(headers.get(FORWARDED_HEADER)).hasSize(2); + assertThat(headers.get(FORWARDED_HEADER)).hasSize(3); List forwardeds = ForwardedRequestHeadersFilter.parse(headers.get(FORWARDED_HEADER)); - assertThat(forwardeds).hasSize(2); - Forwarded addedForwardedHeader = forwardeds.get(0); - Forwarded existingForwardedHeader = forwardeds.get(1); - - assertThat(existingForwardedHeader.getValues()).containsEntry("proto", "http") - .containsEntry("for", "\"10.0.0.1:80\""); - - assertThat(addedForwardedHeader.getValues()).containsEntry("proto", "https") - .containsEntry("for", "23.45.67.89"); + assertThat(forwardeds).hasSize(3); + Optional added = forwardeds.stream() + .filter(forwarded -> forwarded.get("for").contains("10.0.0.1:80")) + .findFirst(); + assertThat(added).isPresent(); + added.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("proto", "http").containsEntry("for", "\"10.0.0.1:80\""); + }); + Optional existing = forwardeds.stream() + .filter(forwarded -> forwarded.get("for").equals("23.45.67.89")) + .findFirst(); + assertThat(existing).isPresent(); + existing.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("for", "23.45.67.89"); + }); + existing = forwardeds.stream().filter(forwarded -> forwarded.get("for").equals("12.34.56.78")).findFirst(); + assertThat(existing).isPresent(); + existing.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("proto", "https").containsEntry("for", "12.34.56.78"); + }); } @Test @@ -113,7 +125,7 @@ public class ForwardedRequestHeadersFilterTests { servletRequest.setRemoteHost("10.0.0.1"); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); - ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(); + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(".*"); HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); @@ -136,7 +148,7 @@ public class ForwardedRequestHeadersFilterTests { servletRequest.setRemoteHost("2001:db8:cafe:0:0:0:0:17"); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); - ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(); + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(".*"); HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); @@ -158,7 +170,7 @@ public class ForwardedRequestHeadersFilterTests { servletRequest.setRemoteHost("unresolvable-hostname"); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); - ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(); + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter(".*"); HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); @@ -211,4 +223,62 @@ public class ForwardedRequestHeadersFilterTests { } } + @Test + public void forwardedHeadersNotTrusted() throws Exception { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .remoteAddress("10.0.0.1:80") + .header(HttpHeaders.HOST, "myhost") + .buildRequest(null); + servletRequest.setRemoteHost("10.0.0.1"); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter("11\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).doesNotContainKeys(FORWARDED_HEADER); + } + + // verify that existing forwarded header is not forwarded if not trusted + @Test + public void untrustedForwardedForNotAppended() throws Exception { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .remoteAddress("10.0.0.1:80") + .header(HttpHeaders.HOST, "myhost") + .header(FORWARDED_HEADER, "proto=http;host=myhost;for=\"127.0.0.1:80\",for=10.0.0.11") + .buildRequest(null); + servletRequest.setRemoteHost("10.0.0.1"); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).containsKeys(FORWARDED_HEADER); + List forwardedHeaders = headers.get(FORWARDED_HEADER); + Optional filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst(); + assertThat(filtered).isEmpty(); + filtered = forwardedHeaders.stream().filter(value -> value.contains("10.0.0.11")).findFirst(); + assertThat(filtered).isNotEmpty(); + } + + @Test + public void remoteAdddressIsNullUnTrustedProxyNotAppended() throws Exception { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .header(HttpHeaders.HOST, "myhost") + .header(FORWARDED_HEADER, "proto=http;host=myhost;for=127.0.0.1") + .buildRequest(null); + servletRequest.setRemoteAddr(null); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + ForwardedRequestHeadersFilter filter = new ForwardedRequestHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).containsKeys(FORWARDED_HEADER); + List forwardedHeaders = headers.get(FORWARDED_HEADER); + Optional filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst(); + assertThat(filtered).isEmpty(); + } + } 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 new file mode 100644 index 00000000..f9c27a91 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/XForwardedRequestHeadersFilterTests.java @@ -0,0 +1,162 @@ +/* + * Copyright 2013-2023 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.server.mvc.filter; + +import java.util.Collections; + +import org.assertj.core.api.Assertions; +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.http.HttpHeaders; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.servlet.function.ServerRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER; +import static org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER; +import static org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER; +import static org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER; + +/** + * @author Spencer Gibb + */ +public class XForwardedRequestHeadersFilterTests { + + @Test + public void remoteAddressIsNull() { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .header(HttpHeaders.HOST, "myhost") + .buildRequest(null); + servletRequest.setRemoteAddr(null); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + XForwardedRequestHeadersFilter filter = new XForwardedRequestHeadersFilter( + new XForwardedRequestHeadersFilterProperties(), ".*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER) + .containsKeys(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER); + + assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("myhost"); + assertThat(headers.getFirst(X_FORWARDED_PORT_HEADER)).isEqualTo("80"); + assertThat(headers.getFirst(X_FORWARDED_PROTO_HEADER)).isEqualTo("http"); + } + + @Test + public void trustedProxiesConditionMatches() { + new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, + SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + GatewayServerMvcAutoConfiguration.class)) + .withPropertyValues(GatewayMvcProperties.PREFIX + ".trusted-proxies=11\\.0\\.0\\..*") + .run(context -> { + assertThat(context).hasSingleBean(XForwardedRequestHeadersFilter.class); + }); + } + + @Test + public void trustedProxiesConditionDoesNotMatch() { + new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebMvcAutoConfiguration.class, RestClientAutoConfiguration.class, + SslAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class, + GatewayServerMvcAutoConfiguration.class)) + .run(context -> { + assertThat(context).doesNotHaveBean(XForwardedRequestHeadersFilter.class); + }); + } + + @Test + public void emptyTrustedProxiesFails() { + Assertions + .assertThatThrownBy( + () -> new XForwardedRequestHeadersFilter(new XForwardedRequestHeadersFilterProperties(), "")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void xForwardedHeadersNotTrusted() throws Exception { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .remoteAddress("10.0.0.1:80") + .header(HttpHeaders.HOST, "myhost") + .buildRequest(null); + servletRequest.setRemoteHost("10.0.0.1"); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + XForwardedRequestHeadersFilter filter = new XForwardedRequestHeadersFilter( + new XForwardedRequestHeadersFilterProperties(), "11\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + } + + // verify that existing forwarded header is not forwarded if not trusted + @Test + public void untrustedXForwardedForNotAppended() { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .remoteAddress("10.0.0.1:80") + .header(HttpHeaders.HOST, "myhost") + .header(X_FORWARDED_FOR_HEADER, "127.0.0.1") + .header(X_FORWARDED_FOR_HEADER, "10.0.0.10") + .buildRequest(null); + servletRequest.setRemoteHost("10.0.0.1"); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + XForwardedRequestHeadersFilter filter = new XForwardedRequestHeadersFilter( + new XForwardedRequestHeadersFilterProperties(), "10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + + assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1") + .contains("10.0.0.1", "10.0.0.10"); + } + + @Test + public void remoteAdddressIsNullUnTrustedProxyNotAppended() { + MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get") + .header(HttpHeaders.HOST, "myhost") + .header(X_FORWARDED_FOR_HEADER, "127.0.0.1") + .buildRequest(null); + servletRequest.setRemoteAddr(null); + ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); + + XForwardedRequestHeadersFilter filter = new XForwardedRequestHeadersFilter( + new XForwardedRequestHeadersFilterProperties(), "10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.apply(request.headers().asHttpHeaders(), request); + + assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + + assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1"); + } + +} diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/TestUtils.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/TestUtils.java index c0e6556c..d8bad981 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/TestUtils.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/TestUtils.java @@ -22,7 +22,11 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -public class TestUtils { +public final class TestUtils { + + private TestUtils() { + + } public static Map getMap(Map map, String mapKey) { assertThat(map).isNotEmpty().containsKey(mapKey); diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application.yml index 9bc1759e..94788e61 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application.yml @@ -6,4 +6,8 @@ logging: org.springframework.retry: TRACE spring: mvc: - log-request-details: true \ No newline at end of file + log-request-details: true + cloud: + gateway: + mvc: + trusted-proxies: .* \ No newline at end of file diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/DefaultNettyHttpForwardedHeaderHandler.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/DefaultNettyHttpForwardedHeaderHandler.java new file mode 100644 index 00000000..b8893728 --- /dev/null +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/DefaultNettyHttpForwardedHeaderHandler.java @@ -0,0 +1,137 @@ +/* + * Copyright 2013-2024 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. + */ + +/* + * Copyright (c) 2020-2023 VMware, Inc. or its affiliates, All Rights Reserved. + * + * 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.config; + +import java.util.function.BiFunction; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.netty.handler.codec.http.HttpRequest; +import reactor.netty.http.server.ConnectionInfo; +import reactor.netty.transport.AddressUtils; + +import static reactor.netty.http.server.ConnectionInfo.getDefaultHostPort; + +/** + * Default implementation for handling {@code X-Forwarded}/{@code Forwarded} headers. + * + * @author Andrey Shlykov + * @since 0.9.12 + */ +final class DefaultNettyHttpForwardedHeaderHandler implements BiFunction { + + static final DefaultNettyHttpForwardedHeaderHandler INSTANCE = new DefaultNettyHttpForwardedHeaderHandler(); + + static final String FORWARDED_HEADER = "Forwarded"; + static final String X_FORWARDED_IP_HEADER = "X-Forwarded-For"; + static final String X_FORWARDED_HOST_HEADER = "X-Forwarded-Host"; + static final String X_FORWARDED_PORT_HEADER = "X-Forwarded-Port"; + static final String X_FORWARDED_PROTO_HEADER = "X-Forwarded-Proto"; + + static final Pattern FORWARDED_HOST_PATTERN = Pattern.compile("host=\"?([^;,\"]+)\"?"); + static final Pattern FORWARDED_PROTO_PATTERN = Pattern.compile("proto=\"?([^;,\"]+)\"?"); + static final Pattern FORWARDED_FOR_PATTERN = Pattern.compile("for=\"?([^;,\"]+)\"?"); + + /** + * Specifies whether the Http Server applies a strict {@code Forwarded} header + * validation. By default, it is enabled and strict validation is used. + * @since 1.0.8 + * @deprecated The system property is used for backwards compatibility and will be + * removed in version 1.2.0. + */ + @Deprecated + static final String FORWARDED_HEADER_VALIDATION = "reactor.netty.http.server.forwarded.strictValidation"; + static final boolean DEFAULT_FORWARDED_HEADER_VALIDATION = Boolean + .parseBoolean(System.getProperty(FORWARDED_HEADER_VALIDATION, "true")); + + @Override + public ConnectionInfo apply(ConnectionInfo connectionInfo, HttpRequest request) { + String forwardedHeader = request.headers().get(FORWARDED_HEADER); + if (forwardedHeader != null) { + return parseForwardedInfo(connectionInfo, forwardedHeader); + } + return parseXForwardedInfo(connectionInfo, request); + } + + private ConnectionInfo parseForwardedInfo(ConnectionInfo connectionInfo, String forwardedHeader) { + String forwarded = forwardedHeader.split(",", 2)[0]; + Matcher protoMatcher = FORWARDED_PROTO_PATTERN.matcher(forwarded); + if (protoMatcher.find()) { + connectionInfo = connectionInfo.withScheme(protoMatcher.group(1).trim()); + } + Matcher hostMatcher = FORWARDED_HOST_PATTERN.matcher(forwarded); + if (hostMatcher.find()) { + connectionInfo = connectionInfo.withHostAddress(AddressUtils.parseAddress(hostMatcher.group(1), + getDefaultHostPort(connectionInfo.getScheme()), DEFAULT_FORWARDED_HEADER_VALIDATION)); + } + Matcher forMatcher = FORWARDED_FOR_PATTERN.matcher(forwarded); + if (forMatcher.find()) { + connectionInfo = connectionInfo.withRemoteAddress(AddressUtils.parseAddress(forMatcher.group(1).trim(), + connectionInfo.getRemoteAddress().getPort(), DEFAULT_FORWARDED_HEADER_VALIDATION)); + } + return connectionInfo; + } + + private ConnectionInfo parseXForwardedInfo(ConnectionInfo connectionInfo, HttpRequest request) { + String ipHeader = request.headers().get(X_FORWARDED_IP_HEADER); + if (ipHeader != null) { + connectionInfo = connectionInfo.withRemoteAddress( + AddressUtils.parseAddress(ipHeader.split(",", 2)[0], connectionInfo.getRemoteAddress().getPort())); + } + String protoHeader = request.headers().get(X_FORWARDED_PROTO_HEADER); + if (protoHeader != null) { + connectionInfo = connectionInfo.withScheme(protoHeader.split(",", 2)[0].trim()); + } + String hostHeader = request.headers().get(X_FORWARDED_HOST_HEADER); + if (hostHeader != null) { + connectionInfo = connectionInfo + .withHostAddress(AddressUtils.parseAddress(hostHeader.split(",", 2)[0].trim(), + getDefaultHostPort(connectionInfo.getScheme()), DEFAULT_FORWARDED_HEADER_VALIDATION)); + } + + String portHeader = request.headers().get(X_FORWARDED_PORT_HEADER); + if (portHeader != null && !portHeader.isEmpty()) { + String portStr = portHeader.split(",", 2)[0].trim(); + if (portStr.chars().allMatch(Character::isDigit)) { + int port = Integer.parseInt(portStr); + connectionInfo = connectionInfo.withHostAddress( + AddressUtils.createUnresolved(connectionInfo.getHostAddress().getHostString(), port), + connectionInfo.getHostName(), port); + } + else if (DEFAULT_FORWARDED_HEADER_VALIDATION) { + throw new IllegalArgumentException("Failed to parse a port from " + portHeader); + } + } + return connectionInfo; + } + +} 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 3a63edaf..54ad4c1e 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 @@ -17,6 +17,7 @@ package org.springframework.cloud.gateway.config; import java.io.IOException; +import java.net.InetSocketAddress; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -59,6 +60,7 @@ import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfigurat import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint; import org.springframework.cloud.gateway.config.conditional.ConditionalOnEnabledFilter; @@ -123,6 +125,7 @@ import org.springframework.cloud.gateway.filter.headers.GRPCResponseHeadersFilte import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter; import org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter; import org.springframework.cloud.gateway.filter.headers.TransferEncodingNormalizationHeadersFilter; +import org.springframework.cloud.gateway.filter.headers.TrustedProxies; import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver; @@ -174,6 +177,7 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; import org.springframework.validation.Validator; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; @@ -312,9 +316,9 @@ public class GatewayAutoConfiguration { } @Bean - @ConditionalOnProperty(name = "spring.cloud.gateway.forwarded.enabled", matchIfMissing = true) - public ForwardedHeadersFilter forwardedHeadersFilter() { - return new ForwardedHeadersFilter(); + @Conditional(TrustedProxies.ForwardedTrustedProxiesCondition.class) + public ForwardedHeadersFilter forwardedHeadersFilter(GatewayProperties properties) { + return new ForwardedHeadersFilter(properties.getTrustedProxies()); } // HttpHeaderFilter beans @@ -325,9 +329,9 @@ public class GatewayAutoConfiguration { } @Bean - @ConditionalOnProperty(name = "spring.cloud.gateway.x-forwarded.enabled", matchIfMissing = true) - public XForwardedHeadersFilter xForwardedHeadersFilter() { - return new XForwardedHeadersFilter(); + @Conditional(TrustedProxies.XForwardedTrustedProxiesCondition.class) + public XForwardedHeadersFilter xForwardedHeadersFilter(GatewayProperties properties) { + return new XForwardedHeadersFilter(properties.getTrustedProxies()); } @Bean @@ -757,6 +761,21 @@ public class GatewayAutoConfiguration { }; } + @Bean + @TrustedProxies.ConditionalOnPropertyExists + public NettyServerCustomizer gatewayNettyServerCustomizer(GatewayProperties gatewayProperties) { + TrustedProxies trustedProxies = TrustedProxies.from(gatewayProperties.getTrustedProxies()); + + return httpServer -> httpServer.forwarded((connectionInfo, httpRequest) -> { + InetSocketAddress remoteAddress = connectionInfo.getRemoteAddress(); + if (remoteAddress != null && trustedProxies.isTrusted(remoteAddress.getHostString())) { + // update remote address + return DefaultNettyHttpForwardedHeaderHandler.INSTANCE.apply(connectionInfo, httpRequest); + } + return connectionInfo; + }); + } + @Bean public HttpClientSslConfigurer httpClientSslConfigurer(ServerProperties serverProperties, HttpClientProperties httpClientProperties) { diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java index 53ea714c..95333cd6 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayProperties.java @@ -68,6 +68,12 @@ public class GatewayProperties { */ private boolean failOnRouteDefinitionError = true; + /** + * Regular expression defining proxies that are trusted when they appear in a + * Forwarded or X-Forwarded header. + */ + private String trustedProxies; + public List getRoutes() { return routes; } @@ -103,12 +109,21 @@ public class GatewayProperties { this.failOnRouteDefinitionError = failOnRouteDefinitionError; } + public String getTrustedProxies() { + return trustedProxies; + } + + public void setTrustedProxies(String trustedProxies) { + this.trustedProxies = trustedProxies; + } + @Override public String toString() { return new ToStringCreator(this).append("routes", routes) .append("defaultFilters", defaultFilters) .append("streamingMediaTypes", streamingMediaTypes) .append("failOnRouteDefinitionError", failOnRouteDefinitionError) + .append("trustedProxies", trustedProxies) .toString(); } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilter.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilter.java index b95cb191..e8254917 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilter.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/ForwardedHeadersFilter.java @@ -25,7 +25,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.core.Ordered; +import org.springframework.core.log.LogMessage; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.CollectionUtils; @@ -36,11 +41,26 @@ import org.springframework.web.server.ServerWebExchange; public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { + private static final Log log = LogFactory.getLog(ForwardedHeadersFilter.class); + /** * Forwarded header. */ public static final String FORWARDED_HEADER = "Forwarded"; + private final TrustedProxies trustedProxies; + + @Deprecated + public ForwardedHeadersFilter() { + trustedProxies = s -> true; + log.warn(GatewayProperties.PREFIX + + ".trusted-proxies is not set. Using deprecated Constructor. Untrusted hosts might be added to Forwarded header."); + } + + public ForwardedHeadersFilter(String trustedProxiesRegex) { + trustedProxies = TrustedProxies.from(trustedProxiesRegex); + } + /* for testing */ static List parse(List values) { ArrayList forwardeds = new ArrayList<>(); @@ -48,8 +68,11 @@ public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { return forwardeds; } for (String value : values) { - Forwarded forwarded = parse(value); - forwardeds.add(forwarded); + String[] forwardedValues = StringUtils.tokenizeToStringArray(value, ","); + for (String forwardedValue : forwardedValues) { + Forwarded forwarded = parse(forwardedValue); + forwardeds.add(forwarded); + } } return forwardeds; } @@ -92,6 +115,14 @@ public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { @Override public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); + + if (request.getRemoteAddress() != null + && !trustedProxies.isTrusted(request.getRemoteAddress().getHostString())) { + log.trace(LogMessage.format("Remote address not trusted. pattern %s remote address %s", trustedProxies, + request.getRemoteAddress())); + return input; + } + HttpHeaders original = input; HttpHeaders updated = new HttpHeaders(); @@ -105,7 +136,10 @@ public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { List forwardeds = parse(original.get(FORWARDED_HEADER)); for (Forwarded f : forwardeds) { - updated.add(FORWARDED_HEADER, f.toHeaderValue()); + // only add if "for" value matches trustedProxies + if (trustedProxies.isTrusted(f.get("for"))) { + updated.add(FORWARDED_HEADER, f.toHeaderValue()); + } } // TODO: add new forwarded @@ -114,6 +148,7 @@ public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { Forwarded forwarded = new Forwarded().put("host", host).put("proto", uri.getScheme()); InetSocketAddress remoteAddress = request.getRemoteAddress(); + // TODO: only add if "remoteAddress" value matches trustedProxies if (remoteAddress != null) { // If remoteAddress is unresolved, calling getHostAddress() would cause a // NullPointerException. @@ -128,11 +163,14 @@ public class ForwardedHeadersFilter implements HttpHeadersFilter, Ordered { forValue = "[" + forValue + "]"; } } - int port = remoteAddress.getPort(); - if (port >= 0) { - forValue = forValue + ":" + port; + if (trustedProxies.isTrusted(forValue)) { + // only add for value if trusted + int port = remoteAddress.getPort(); + if (port >= 0) { + forValue = forValue + ":" + port; + } + forwarded.put("for", forValue); } - forwarded.put("for", forValue); } // TODO: support by? diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java new file mode 100644 index 00000000..da80a99a --- /dev/null +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java @@ -0,0 +1,114 @@ +/* + * 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.filter.headers; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +import org.springframework.boot.autoconfigure.condition.AllNestedConditions; +import org.springframework.boot.autoconfigure.condition.ConditionOutcome; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.cloud.gateway.config.GatewayProperties; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.lang.NonNull; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +@FunctionalInterface +public interface TrustedProxies { + + String PROPERTY = GatewayProperties.PREFIX + ".trusted-proxies"; + + boolean isTrusted(String host); + + static TrustedProxies from(@NonNull String trustedProxies) { + Assert.hasText(trustedProxies, "trustedProxies must not be empty"); + Pattern pattern = Pattern.compile(trustedProxies); + return value -> pattern.matcher(value).matches(); + } + + class ForwardedTrustedProxiesCondition extends AllNestedConditions { + + public ForwardedTrustedProxiesCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnProperty(name = GatewayProperties.PREFIX + ".forwarded.enabled", matchIfMissing = true) + static class OnPropertyEnabled { + + } + + @ConditionalOnPropertyExists + static class OnTrustedProxiesNotEmpty { + + } + + } + + class XForwardedTrustedProxiesCondition extends AllNestedConditions { + + public XForwardedTrustedProxiesCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnProperty(name = GatewayProperties.PREFIX + ".x-forwarded.enabled", matchIfMissing = true) + static class OnPropertyEnabled { + + } + + @ConditionalOnPropertyExists + static class OnTrustedProxiesNotEmpty { + + } + + } + + class OnPropertyExistsCondition extends SpringBootCondition { + + @Override + public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { + try { + String property = context.getEnvironment().getProperty(PROPERTY); + if (!StringUtils.hasText(property)) { + return ConditionOutcome.noMatch(PROPERTY + " property is not set or is empty."); + } + return ConditionOutcome.match(PROPERTY + " property is not empty."); + } + catch (NoSuchElementException e) { + return ConditionOutcome.noMatch("Missing required property 'value' of @ConditionalOnPropertyExists"); + } + } + + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ ElementType.TYPE, ElementType.METHOD }) + @Documented + @Conditional(OnPropertyExistsCondition.class) + @interface ConditionalOnPropertyExists { + + } + +} diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilter.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilter.java index 2c1e8363..bbf78c42 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilter.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilter.java @@ -20,9 +20,15 @@ import java.net.URI; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.function.Predicate; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.core.Ordered; +import org.springframework.core.log.LogMessage; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.ObjectUtils; @@ -35,6 +41,8 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G @ConfigurationProperties("spring.cloud.gateway.x-forwarded") public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { + private static final Log log = LogFactory.getLog(XForwardedHeadersFilter.class); + /** Default http port. */ public static final int HTTP_PORT = 80; @@ -98,6 +106,19 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { /** If appending X-Forwarded-Prefix as a list is enabled. */ private boolean prefixAppend = true; + private final TrustedProxies trustedProxies; + + @Deprecated + public XForwardedHeadersFilter() { + trustedProxies = s -> true; + log.warn(GatewayProperties.PREFIX + + ".trusted-proxies is not set. Using deprecated Constructor. Untrusted hosts might be added to Forwarded header."); + } + + public XForwardedHeadersFilter(String trustedProxiesRegex) { + trustedProxies = TrustedProxies.from(trustedProxiesRegex); + } + @Override public int getOrder() { return this.order; @@ -197,8 +218,15 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { @Override public HttpHeaders filter(HttpHeaders input, ServerWebExchange exchange) { - ServerHttpRequest request = exchange.getRequest(); + + if (request.getRemoteAddress() != null + && !trustedProxies.isTrusted(request.getRemoteAddress().getHostString())) { + log.trace(LogMessage.format("Remote address not trusted. pattern %s remote address %s", trustedProxies, + request.getRemoteAddress())); + return input; + } + HttpHeaders original = input; HttpHeaders updated = new HttpHeaders(); @@ -206,9 +234,13 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { updated.addAll(entry.getKey(), entry.getValue()); } - if (isForEnabled() && request.getRemoteAddress() != null && request.getRemoteAddress().getAddress() != null) { - String remoteAddr = request.getRemoteAddress().getAddress().getHostAddress(); - write(updated, X_FORWARDED_FOR_HEADER, remoteAddr, isForAppend()); + if (isForEnabled()) { + String remoteAddr = null; + if (request.getRemoteAddress() != null && request.getRemoteAddress().getAddress() != null) { + remoteAddr = request.getRemoteAddress().getHostString(); + } + // match xforwarded for against trusted proxies + write(updated, X_FORWARDED_FOR_HEADER, remoteAddr, isForAppend(), trustedProxies::isTrusted); } String proto = request.getURI().getScheme(); @@ -284,17 +316,22 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { } private void write(HttpHeaders headers, String name, String value, boolean append) { - if (value == null) { - return; - } + write(headers, name, value, append, s -> true); + } + + private void write(HttpHeaders headers, String name, String value, boolean append, Predicate shouldWrite) { if (append) { - headers.add(name, value); + if (value != null) { + headers.add(name, value); + } // these headers should be treated as a single comma separated header - List values = headers.get(name); - String delimitedValue = StringUtils.collectionToCommaDelimitedString(values); - headers.set(name, delimitedValue); + if (headers.containsKey(name)) { + List values = headers.get(name).stream().filter(shouldWrite).toList(); + String delimitedValue = StringUtils.collectionToCommaDelimitedString(values); + headers.set(name, delimitedValue); + } } - else { + else if (value != null && shouldWrite.test(value)) { headers.set(name, value); } } @@ -303,11 +340,6 @@ public class XForwardedHeadersFilter implements HttpHeadersFilter, Ordered { return HTTPS_SCHEME.equals(scheme) ? HTTPS_PORT : HTTP_PORT; } - private boolean hasHeader(ServerHttpRequest request, String name) { - HttpHeaders headers = request.getHeaders(); - return headers.containsKey(name) && StringUtils.hasLength(headers.getFirst(name)); - } - private String toHostHeader(ServerHttpRequest request) { int port = request.getURI().getPort(); String host = request.getURI().getHost(); 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 c85a1969..58921e99 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 @@ -53,8 +53,10 @@ import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint; import org.springframework.cloud.gateway.config.GatewayAutoConfigurationTests.CustomHttpClientFactory.CustomSslConfigurer; import org.springframework.cloud.gateway.filter.factory.TokenRelayGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.headers.GRPCRequestHeadersFilter; import org.springframework.cloud.gateway.filter.headers.GRPCResponseHeadersFilter; +import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.GatewayFilterSpec; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; @@ -196,8 +198,8 @@ public class GatewayAutoConfigurationTests { "spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect", "spring.security.oauth2.client.registration[test].client-id=login-client") .run(context -> { - assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class); - assertThat(context).hasSingleBean(TokenRelayGatewayFilterFactory.class); + assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class) + .hasSingleBean(TokenRelayGatewayFilterFactory.class); }); } @@ -215,8 +217,8 @@ public class GatewayAutoConfigurationTests { "spring.security.oauth2.client.registration[test].redirect-uri=http://localhost/redirect", "spring.security.oauth2.client.registration[test].client-id=login-client") .run(context -> { - assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class); - assertThat(context).hasBean("myReactiveOAuth2AuthorizedClientManager"); + assertThat(context).hasSingleBean(ReactiveOAuth2AuthorizedClientManager.class) + .hasBean("myReactiveOAuth2AuthorizedClientManager"); }); } @@ -279,8 +281,8 @@ public class GatewayAutoConfigurationTests { HttpClientCustomizedConfig.class, ServerPropertiesConfig.class)) .withPropertyValues("server.http2.enabled=true") .run(context -> { - assertThat(context).hasSingleBean(GRPCRequestHeadersFilter.class); - assertThat(context).hasSingleBean(GRPCResponseHeadersFilter.class); + assertThat(context).hasSingleBean(GRPCRequestHeadersFilter.class) + .hasSingleBean(GRPCResponseHeadersFilter.class); HttpClient httpClient = context.getBean(HttpClient.class); assertThat(httpClient.configuration().protocols()).contains(HttpProtocol.HTTP11, HttpProtocol.H2); }); @@ -294,8 +296,8 @@ public class GatewayAutoConfigurationTests { HttpClientCustomizedConfig.class, ServerPropertiesConfig.class)) .withPropertyValues("server.http2.enabled=false") .run(context -> { - assertThat(context).doesNotHaveBean(GRPCRequestHeadersFilter.class); - assertThat(context).doesNotHaveBean(GRPCResponseHeadersFilter.class); + assertThat(context).doesNotHaveBean(GRPCRequestHeadersFilter.class) + .doesNotHaveBean(GRPCResponseHeadersFilter.class); }); } @@ -326,6 +328,32 @@ public class GatewayAutoConfigurationTests { }); } + @Test + public void forwardedHeaderFiltersNotEnabledByDefault() { + new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, MetricsAutoConfiguration.class, + SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class, + ServerPropertiesConfig.class)) + .run(context -> { + assertThat(context).doesNotHaveBean(XForwardedHeadersFilter.class) + .doesNotHaveBean(ForwardedHeadersFilter.class); + }); + } + + @Test + public void forwardedHeaderFiltersEnabledWithProperties() { + new ReactiveWebApplicationContextRunner() + .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=.*") + .run(context -> { + assertThat(context).hasSingleBean(XForwardedHeadersFilter.class) + .hasSingleBean(ForwardedHeadersFilter.class); + }); + } + @Configuration @EnableConfigurationProperties(ServerProperties.class) @AutoConfigureBefore(GatewayAutoConfiguration.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 fb1439d1..f2ecee63 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,7 +66,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @SpringBootTest(webEnvironment = RANDOM_PORT, properties = { "spring.cloud.gateway.httpclient.connect-timeout=500", "spring.cloud.gateway.httpclient.response-timeout=2s", - "logging.level.org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory=TRACE" }) + "logging.level.org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory=TRACE", + "spring.cloud.gateway.trusted-proxies=.*", "spring.cloud.gateway.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 73cb0003..ae24a969 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 @@ -24,9 +24,16 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; +import org.springframework.cloud.gateway.config.GatewayAutoConfiguration; import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter.Forwarded; import org.springframework.http.HttpHeaders; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; @@ -59,7 +66,7 @@ public class ForwardedHeadersFilterTests { .header(HttpHeaders.HOST, "myhost") .build(); - ForwardedHeadersFilter filter = new ForwardedHeadersFilter(); + ForwardedHeadersFilter filter = new ForwardedHeadersFilter(".*"); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -79,26 +86,37 @@ public class ForwardedHeadersFilterTests { public void forwardedHeaderExists() throws UnknownHostException { MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get") .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) - .header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https; for=23.45.67.89") + .header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https, for=23.45.67.89") .build(); - ForwardedHeadersFilter filter = new ForwardedHeadersFilter(); + ForwardedHeadersFilter filter = new ForwardedHeadersFilter(".*"); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); - assertThat(headers.get(FORWARDED_HEADER)).hasSize(2); + assertThat(headers.get(FORWARDED_HEADER)).hasSize(3); List forwardeds = ForwardedHeadersFilter.parse(headers.get(FORWARDED_HEADER)); - assertThat(forwardeds).hasSize(2); - Forwarded addedForwardedHeader = forwardeds.get(0); - Forwarded existingForwardedHeader = forwardeds.get(1); - - assertThat(existingForwardedHeader.getValues()).containsEntry("proto", "http") - .containsEntry("for", "\"10.0.0.1:80\""); - - assertThat(addedForwardedHeader.getValues()).containsEntry("proto", "https") - .containsEntry("for", "23.45.67.89"); + assertThat(forwardeds).hasSize(3); + Optional added = forwardeds.stream() + .filter(forwarded -> forwarded.get("for").contains("10.0.0.1:80")) + .findFirst(); + assertThat(added).isPresent(); + added.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("proto", "http").containsEntry("for", "\"10.0.0.1:80\""); + }); + Optional existing = forwardeds.stream() + .filter(forwarded -> forwarded.get("for").equals("23.45.67.89")) + .findFirst(); + assertThat(existing).isPresent(); + existing.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("for", "23.45.67.89"); + }); + existing = forwardeds.stream().filter(forwarded -> forwarded.get("for").equals("12.34.56.78")).findFirst(); + assertThat(existing).isPresent(); + existing.ifPresent(forwarded -> { + assertThat(forwarded.getValues()).containsEntry("proto", "https").containsEntry("for", "12.34.56.78"); + }); } @Test @@ -107,7 +125,7 @@ public class ForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - ForwardedHeadersFilter filter = new ForwardedHeadersFilter(); + ForwardedHeadersFilter filter = new ForwardedHeadersFilter(".*"); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -128,7 +146,7 @@ public class ForwardedHeadersFilterTests { .header(HttpHeaders.HOST, "myhost") .build(); - ForwardedHeadersFilter filter = new ForwardedHeadersFilter(); + ForwardedHeadersFilter filter = new ForwardedHeadersFilter(".*"); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -148,7 +166,7 @@ public class ForwardedHeadersFilterTests { .remoteAddress(InetSocketAddress.createUnresolved("unresolvable-hostname", 80)) .build(); - ForwardedHeadersFilter filter = new ForwardedHeadersFilter(); + ForwardedHeadersFilter filter = new ForwardedHeadersFilter(".*"); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -201,4 +219,83 @@ public class ForwardedHeadersFilterTests { } } + @Test + public void trustedProxiesConditionMatches() { + new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) + .withPropertyValues("spring.cloud.gateway.trusted-proxies=11\\.0\\.0\\..*") + .run(context -> { + assertThat(context).hasSingleBean(ForwardedHeadersFilter.class); + }); + } + + @Test + public void trustedProxiesConditionDoesNotMatch() { + new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) + .run(context -> { + assertThat(context).doesNotHaveBean(ForwardedHeadersFilter.class); + }); + } + + @Test + public void emptyTrustedProxiesFails() { + Assertions.assertThatThrownBy(() -> new ForwardedHeadersFilter("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void forwardedHeadersNotTrusted() throws Exception { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get") + .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) + .header(HttpHeaders.HOST, "myhost") + .build(); + + ForwardedHeadersFilter filter = new ForwardedHeadersFilter("11\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).doesNotContainKeys(FORWARDED_HEADER); + } + + // verify that existing forwarded header is not forwarded if not trusted + @Test + public void untrustedForwardedForNotAppended() throws Exception { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost/get") + .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) + .header(HttpHeaders.HOST, "myhost") + .header(FORWARDED_HEADER, "proto=http;host=myhost;for=\"127.0.0.1:80\",for=10.0.0.11") + .build(); + + ForwardedHeadersFilter filter = new ForwardedHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).containsKeys(FORWARDED_HEADER); + List forwardedHeaders = headers.get(FORWARDED_HEADER); + Optional filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst(); + assertThat(filtered).isEmpty(); + filtered = forwardedHeaders.stream().filter(value -> value.contains("10.0.0.11")).findFirst(); + assertThat(filtered).isNotEmpty(); + } + + @Test + public void remoteAdddressIsNullUnTrustedProxyNotAppended() throws Exception { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/get") + .header(HttpHeaders.HOST, "myhost") + .header(FORWARDED_HEADER, "proto=http;host=myhost;for=127.0.0.1") + .build(); + + ForwardedHeadersFilter filter = new ForwardedHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).containsKeys(FORWARDED_HEADER); + List forwardedHeaders = headers.get(FORWARDED_HEADER); + Optional filtered = forwardedHeaders.stream().filter(value -> value.contains("127.0.0.1")).findFirst(); + assertThat(filtered).isEmpty(); + } + } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java index 5bfcd7e8..640b02e3 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java @@ -21,8 +21,15 @@ import java.net.InetSocketAddress; import java.net.URI; import java.util.LinkedHashSet; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration; +import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; +import org.springframework.cloud.gateway.config.GatewayAutoConfiguration; +import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.http.HttpHeaders; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -43,17 +50,20 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G */ public class XForwardedHeadersFilterTests { + public static final String ALLOW_ALL_REGEX = ".*"; + @Test public void remoteAddressIsNull() throws Exception { MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/get") .header(HttpHeaders.HOST, "myhost") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); - assertThat(headers).containsKeys(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER); + assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER) + .containsKeys(X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, X_FORWARDED_PROTO_HEADER); assertThat(headers.getFirst(X_FORWARDED_HOST_HEADER)).isEqualTo("localhost:8080"); assertThat(headers.getFirst(X_FORWARDED_PORT_HEADER)).isEqualTo("8080"); @@ -67,7 +77,7 @@ public class XForwardedHeadersFilterTests { .header(HttpHeaders.HOST, "myhost") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -87,7 +97,7 @@ public class XForwardedHeadersFilterTests { .header(HttpHeaders.HOST, "myhost") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -110,7 +120,7 @@ public class XForwardedHeadersFilterTests { .header(X_FORWARDED_PROTO_HEADER, "https") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -134,7 +144,7 @@ public class XForwardedHeadersFilterTests { .header(X_FORWARDED_PREFIX_HEADER, "/prefix") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setForAppend(false); filter.setHostAppend(false); filter.setPortAppend(false); @@ -159,7 +169,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setPrefixAppend(true); filter.setPrefixEnabled(true); @@ -184,7 +194,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setPrefixAppend(true); filter.setPrefixEnabled(true); @@ -210,7 +220,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setPrefixAppend(true); filter.setPrefixEnabled(true); @@ -232,7 +242,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setPrefixAppend(true); filter.setPrefixEnabled(true); filter.setForEnabled(false); @@ -258,7 +268,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setPrefixAppend(true); filter.setPrefixEnabled(true); filter.setForEnabled(false); @@ -284,7 +294,7 @@ public class XForwardedHeadersFilterTests { .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); filter.setForEnabled(false); filter.setHostEnabled(false); filter.setPortEnabled(false); @@ -303,7 +313,7 @@ public class XForwardedHeadersFilterTests { .header(X_FORWARDED_FOR_HEADER, "10.0.0.1") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); @@ -319,11 +329,92 @@ public class XForwardedHeadersFilterTests { .header(X_FORWARDED_FOR_HEADER, "10.0.0.1") .build(); - XForwardedHeadersFilter filter = new XForwardedHeadersFilter(); + XForwardedHeadersFilter filter = new XForwardedHeadersFilter(ALLOW_ALL_REGEX); HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); assertThat(headers).doesNotContainKeys(X_FORWARDED_PROTO_HEADER, X_FORWARDED_HOST_HEADER); } + @Test + public void trustedProxiesConditionMatches() { + new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) + .withPropertyValues(GatewayProperties.PREFIX + ".trusted-proxies=11\\.0\\.0\\..*") + .run(context -> { + assertThat(context).hasSingleBean(XForwardedHeadersFilter.class); + }); + } + + @Test + public void trustedProxiesConditionDoesNotMatch() { + new ReactiveWebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) + .run(context -> { + assertThat(context).doesNotHaveBean(XForwardedHeadersFilter.class); + }); + } + + @Test + public void emptyTrustedProxiesFails() { + Assertions.assertThatThrownBy(() -> new XForwardedHeadersFilter("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void xForwardedHeadersNotTrusted() throws Exception { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/get") + .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) + .header(HttpHeaders.HOST, "myhost") + .build(); + + XForwardedHeadersFilter filter = new XForwardedHeadersFilter("11\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).doesNotContainKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + } + + // : verify that existing x-forwarded-* headers are not forwarded + // if x-forwarded-for is not trusted + @Test + public void untrustedXForwardedForNotAppended() throws Exception { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/get") + .remoteAddress(new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 80)) + .header(HttpHeaders.HOST, "myhost") + .header(X_FORWARDED_FOR_HEADER, "127.0.0.1") + .header(X_FORWARDED_FOR_HEADER, "10.0.0.10") + .build(); + + XForwardedHeadersFilter filter = new XForwardedHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + + assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1") + .contains("10.0.0.1", "10.0.0.10"); + } + + @Test + public void remoteAdddressIsNullUnTrustedProxyNotAppended() { + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080/get") + .header(HttpHeaders.HOST, "myhost") + .header(X_FORWARDED_FOR_HEADER, "127.0.0.1") + .build(); + + XForwardedHeadersFilter filter = new XForwardedHeadersFilter("10\\.0\\.0\\..*"); + + HttpHeaders headers = filter.filter(request.getHeaders(), MockServerWebExchange.from(request)); + + assertThat(headers).containsKeys(X_FORWARDED_FOR_HEADER, X_FORWARDED_HOST_HEADER, X_FORWARDED_PORT_HEADER, + X_FORWARDED_PROTO_HEADER); + + assertThat(headers.getFirst(X_FORWARDED_FOR_HEADER)).doesNotContain("127.0.0.1"); + } + } 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 30bade58..12fa6eab 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 @@ -57,7 +57,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.cloud.gateway.test.TestUtils.getMap; -@SpringBootTest(webEnvironment = RANDOM_PORT) +@SpringBootTest(webEnvironment = RANDOM_PORT, + properties = { "spring.cloud.gateway.forwarded.enabled=true", "spring.cloud.gateway.x-forwarded.enabled=true", + "spring.cloud.gateway.trusted-proxies=.*", + "logging.level.org.springframework.cloud.gateway.filter.headers=TRACE" }) @DirtiesContext @SuppressWarnings("unchecked") class GatewayIntegrationTests extends BaseWebClientTests { diff --git a/spring-cloud-gateway-server/src/test/resources/application-remote-address.yml b/spring-cloud-gateway-server/src/test/resources/application-remote-address.yml index 12795440..013e452b 100644 --- a/spring-cloud-gateway-server/src/test/resources/application-remote-address.yml +++ b/spring-cloud-gateway-server/src/test/resources/application-remote-address.yml @@ -22,3 +22,4 @@ spring: filters: - SetPath=/httpbin/ - SetStatus=200 + trusted-proxies: .* From 5540919fca20cc9a1217c28d433e1c152e863bc1 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 28 May 2025 16:24:10 -0400 Subject: [PATCH 07/20] polishing --- .../cloud/gateway/config/GatewayAutoConfiguration.java | 1 - .../cloud/gateway/filter/headers/TrustedProxies.java | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) 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 54ad4c1e..a8d30869 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 @@ -177,7 +177,6 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; import org.springframework.validation.Validator; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java index da80a99a..732454e8 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/headers/TrustedProxies.java @@ -39,6 +39,9 @@ import org.springframework.util.StringUtils; @FunctionalInterface public interface TrustedProxies { + /** + * Property name. + */ String PROPERTY = GatewayProperties.PREFIX + ".trusted-proxies"; boolean isTrusted(String host); From 79a413ada8ae70af8b599a789b4dbb229ff54876 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Wed, 28 May 2025 21:04:17 +0000 Subject: [PATCH 08/20] Update SNAPSHOT to 4.1.8 --- docs/modules/ROOT/partials/_configprops.adoc | 2 ++ docs/pom.xml | 2 +- pom.xml | 8 ++++---- spring-cloud-gateway-dependencies/pom.xml | 4 ++-- spring-cloud-gateway-integration-tests/grpc/pom.xml | 2 +- spring-cloud-gateway-integration-tests/http2/pom.xml | 2 +- spring-cloud-gateway-integration-tests/httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- spring-cloud-gateway-integration-tests/pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 16 files changed, 21 insertions(+), 19 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 81866e90..70a740c2 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -129,6 +129,7 @@ |spring.cloud.gateway.mvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.mvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. +|spring.cloud.gateway.mvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.mvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -170,6 +171,7 @@ |spring.cloud.gateway.routes | | List of Routes. |spring.cloud.gateway.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. |spring.cloud.gateway.streaming-media-types | | +|spring.cloud.gateway.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. diff --git a/docs/pom.xml b/docs/pom.xml index 6a82d9f3..a391fec6 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index 178f6972..bea897f5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.1.6-SNAPSHOT + 4.1.5 @@ -55,8 +55,8 @@ 1.0.8.RELEASE 17 1.9.1 - 3.1.5-SNAPSHOT - 4.1.6-SNAPSHOT + 3.1.4 + 4.1.5 diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 3b4ad82e..10caa013 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -6,12 +6,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 4.1.6-SNAPSHOT + 4.1.5 spring-cloud-gateway-dependencies - 4.1.8-SNAPSHOT + 4.1.8 pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index c8aad0bf..00d0b3c2 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 0dcf83d0..8053ab0f 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index 08178c87..ab24974f 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 8c679b46..11405840 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index cab51af8..afe74bed 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index 4b87b3db..b224fb30 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 1bf2a253..2d01e905 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index a5b7bd44..054d0813 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 72dbd3d9..53928846 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index b4402605..007a2afc 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 83a6ea16..2610ffaa 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 04911c29..b20b8b02 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.8 .. spring-cloud-starter-gateway From e963342e4cf51f9a7b79c14e7b25166e6951b06b Mon Sep 17 00:00:00 2001 From: spring-builds Date: Wed, 28 May 2025 21:07:05 +0000 Subject: [PATCH 09/20] Going back to snapshots --- docs/modules/ROOT/partials/_configprops.adoc | 2 -- docs/pom.xml | 2 +- pom.xml | 8 ++++---- spring-cloud-gateway-dependencies/pom.xml | 4 ++-- spring-cloud-gateway-integration-tests/grpc/pom.xml | 2 +- spring-cloud-gateway-integration-tests/http2/pom.xml | 2 +- spring-cloud-gateway-integration-tests/httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- spring-cloud-gateway-integration-tests/pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 16 files changed, 19 insertions(+), 21 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 70a740c2..81866e90 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -129,7 +129,6 @@ |spring.cloud.gateway.mvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.mvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. -|spring.cloud.gateway.mvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.mvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -171,7 +170,6 @@ |spring.cloud.gateway.routes | | List of Routes. |spring.cloud.gateway.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. |spring.cloud.gateway.streaming-media-types | | -|spring.cloud.gateway.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. diff --git a/docs/pom.xml b/docs/pom.xml index a391fec6..6a82d9f3 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index bea897f5..178f6972 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.1.5 + 4.1.6-SNAPSHOT @@ -55,8 +55,8 @@ 1.0.8.RELEASE 17 1.9.1 - 3.1.4 - 4.1.5 + 3.1.5-SNAPSHOT + 4.1.6-SNAPSHOT diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 10caa013..3b4ad82e 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -6,12 +6,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 4.1.5 + 4.1.6-SNAPSHOT spring-cloud-gateway-dependencies - 4.1.8 + 4.1.8-SNAPSHOT pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index 00d0b3c2..c8aad0bf 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 8053ab0f..0dcf83d0 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index ab24974f..08178c87 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 11405840..8c679b46 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index afe74bed..cab51af8 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index b224fb30..4b87b3db 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 2d01e905..1bf2a253 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index 054d0813..a5b7bd44 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 53928846..72dbd3d9 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index 007a2afc..b4402605 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 2610ffaa..83a6ea16 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index b20b8b02..04911c29 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8 + 4.1.8-SNAPSHOT .. spring-cloud-starter-gateway From 84603fc6c062572bd0dc5281bdb1dd35431d9352 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Wed, 28 May 2025 21:07:06 +0000 Subject: [PATCH 10/20] Bumping versions to 4.1.9-SNAPSHOT after release --- docs/pom.xml | 2 +- pom.xml | 2 +- spring-cloud-gateway-dependencies/pom.xml | 2 +- spring-cloud-gateway-integration-tests/grpc/pom.xml | 2 +- spring-cloud-gateway-integration-tests/http2/pom.xml | 2 +- spring-cloud-gateway-integration-tests/httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- spring-cloud-gateway-integration-tests/pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 6a82d9f3..33237b02 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index 178f6972..f0dbd8bb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT pom Spring Cloud Gateway diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 3b4ad82e..d0d6d02f 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -11,7 +11,7 @@ spring-cloud-gateway-dependencies - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index c8aad0bf..9353a1e4 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 0dcf83d0..f173952e 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index 08178c87..2bf2fea9 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 8c679b46..e06a6eb4 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index cab51af8..d852d56e 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index 4b87b3db..88849667 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 1bf2a253..6a9e5639 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index a5b7bd44..01ab4b89 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 72dbd3d9..067b3d8b 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index b4402605..413ea68a 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 83a6ea16..5a499ae9 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 04911c29..76050005 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.1.8-SNAPSHOT + 4.1.9-SNAPSHOT .. spring-cloud-starter-gateway From 98fe0acc3a835c00f0d3387b9b23dbeeecaef1f7 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 28 May 2025 17:23:14 -0400 Subject: [PATCH 11/20] Adds trusted-proxies config --- docs/modules/ROOT/partials/_configprops.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index a8eed641..e1ede206 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -131,6 +131,7 @@ |spring.cloud.gateway.mvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.mvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. +|spring.cloud.gateway.mvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.mvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -173,6 +174,7 @@ |spring.cloud.gateway.routes | | List of Routes. |spring.cloud.gateway.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. |spring.cloud.gateway.streaming-media-types | | +|spring.cloud.gateway.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. From b60f8db2c739c5ee22668296dd8beab78c3fa1ba Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 28 May 2025 17:31:08 -0400 Subject: [PATCH 12/20] Escapes curly-braces --- .../spring-cloud-gateway/request-predicates-factories.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway/request-predicates-factories.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway/request-predicates-factories.adoc index c1cb13ee..2a786bb9 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway/request-predicates-factories.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway/request-predicates-factories.adoc @@ -192,7 +192,7 @@ This route matches if the request path was, for example: `/red/1` or `/red/1/` o If `matchTrailingSlash` is set to `false`, then request path `/red/1/` will not be matched. -If you have set `spring.webflux.base-path` property, this will influence the path matching. The property value will be automatically prepended to the path patterns. For example, with `spring.webflux.base-path=/app` and a path pattern of `/red/{segment}`, the full pattern used for matching would be `/app/red/{segment}`. +If you have set `spring.webflux.base-path` property, this will influence the path matching. The property value will be automatically prepended to the path patterns. For example, with `spring.webflux.base-path=/app` and a path pattern of `/red/\{segment\}`, the full pattern used for matching would be `/app/red/\{segment\}`. This predicate extracts the URI template variables (such as `segment`, defined in the preceding example) as a map of names and values and places it in the `ServerWebExchange.getAttributes()` with a key defined in `ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE`. Those values are then available for use by <> From 789697336a15f1d30c33031f567bcf1ccfb2fa9f Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 28 May 2025 17:48:15 -0400 Subject: [PATCH 13/20] Updates for ssl bundles --- .../gateway/filter/headers/ForwardedHeadersFilterTests.java | 5 +++-- .../gateway/filter/headers/XForwardedHeadersFilterTests.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) 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 ae24a969..35679dcb 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 @@ -30,6 +30,7 @@ import org.assertj.core.api.Assertions; 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.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -222,7 +223,7 @@ public class ForwardedHeadersFilterTests { @Test public void trustedProxiesConditionMatches() { new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, SslAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) .withPropertyValues("spring.cloud.gateway.trusted-proxies=11\\.0\\.0\\..*") .run(context -> { @@ -233,7 +234,7 @@ public class ForwardedHeadersFilterTests { @Test public void trustedProxiesConditionDoesNotMatch() { new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, SslAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) .run(context -> { assertThat(context).doesNotHaveBean(ForwardedHeadersFilter.class); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java index 640b02e3..e90d5231 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/headers/XForwardedHeadersFilterTests.java @@ -25,6 +25,7 @@ import org.assertj.core.api.Assertions; 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.reactive.ReactiveWebServerFactoryAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; @@ -339,7 +340,7 @@ public class XForwardedHeadersFilterTests { @Test public void trustedProxiesConditionMatches() { new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, SslAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) .withPropertyValues(GatewayProperties.PREFIX + ".trusted-proxies=11\\.0\\.0\\..*") .run(context -> { @@ -350,7 +351,7 @@ public class XForwardedHeadersFilterTests { @Test public void trustedProxiesConditionDoesNotMatch() { new ReactiveWebApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, + .withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, SslAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class, GatewayAutoConfiguration.class)) .run(context -> { assertThat(context).doesNotHaveBean(XForwardedHeadersFilter.class); From c4670abc41a475fd0119f25c00cb0ede88a14d16 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Wed, 28 May 2025 18:48:19 -0400 Subject: [PATCH 14/20] Updates for new properties namespaces and polish. Fixes some merge errors. Formatting --- .../httpheadersfilters.adoc | 28 +++++++-------- .../httpheadersfilters.adoc | 24 ++++++------- .../XForwardedRequestHeadersFilter.java | 5 +-- ...itional-spring-configuration-metadata.json | 12 +++++++ .../ForwardedRequestHeadersFilterTests.java | 34 +++++++++++++++++++ .../XForwardedRequestHeadersFilterTests.java | 7 ++-- .../config/GatewayAutoConfiguration.java | 3 +- ...itional-spring-configuration-metadata.json | 12 +++++++ .../config/GatewayAutoConfigurationTests.java | 5 +-- ...yGatewayFilterFactoryIntegrationTests.java | 5 +-- .../headers/ForwardedHeadersFilterTests.java | 2 +- .../gateway/test/GatewayIntegrationTests.java | 4 ++- 12 files changed, 104 insertions(+), 37 deletions(-) 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 From 31f72a779bcb9fd25f5890ba5fbf76d6cb573144 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Thu, 29 May 2025 01:46:43 +0000 Subject: [PATCH 15/20] Update SNAPSHOT to 4.3.0 --- docs/modules/ROOT/partials/_configprops.adoc | 115 +++++++++--------- docs/pom.xml | 2 +- pom.xml | 12 +- spring-cloud-gateway-dependencies/pom.xml | 4 +- .../grpc/pom.xml | 2 +- .../http2/pom.xml | 2 +- .../httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server-webflux/pom.xml | 2 +- spring-cloud-gateway-server-webmvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 22 files changed, 86 insertions(+), 83 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 13231741..087392fb 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -1,9 +1,9 @@ |=== |Name | Default | Description -|spring.cloud.gateway | | +|spring.cloud.gateway | | |spring.cloud.gateway.default-filters | | List of filter definitions that are applied to every route. -|spring.cloud.gateway.discovery.locator | | +|spring.cloud.gateway.discovery.locator | | |spring.cloud.gateway.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. |spring.cloud.gateway.discovery.locator.filters | | |spring.cloud.gateway.discovery.locator.include-expression | `+++true+++` | SpEL expression that will evaluate whether to include a service in gateway integration or not, defaults to: true. @@ -21,10 +21,10 @@ |spring.cloud.gateway.filter.fallback-headers.enabled | `+++true+++` | Enables the fallback-headers filter. |spring.cloud.gateway.filter.hystrix.enabled | `+++true+++` | Enables the hystrix filter. |spring.cloud.gateway.filter.json-to-grpc.enabled | `+++true+++` | Enables the JSON to gRPC filter. -|spring.cloud.gateway.filter.local-response-cache | | +|spring.cloud.gateway.filter.local-response-cache | | |spring.cloud.gateway.filter.local-response-cache.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.filter.local-response-cache.request | | -|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|spring.cloud.gateway.filter.local-response-cache.request | | +|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | |spring.cloud.gateway.filter.local-response-cache.size | | Maximum size of the cache to evict entries for this route (in KB, MB and GB). |spring.cloud.gateway.filter.local-response-cache.time-to-live | `+++5m+++` | Time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours). |spring.cloud.gateway.filter.map-request-header.enabled | `+++true+++` | Enables the map-request-header filter. @@ -33,16 +33,16 @@ |spring.cloud.gateway.filter.prefix-path.enabled | `+++true+++` | Enables the prefix-path filter. |spring.cloud.gateway.filter.preserve-host-header.enabled | `+++true+++` | Enables the preserve-host-header filter. |spring.cloud.gateway.filter.redirect-to.enabled | `+++true+++` | Enables the redirect-to filter. -|spring.cloud.gateway.filter.remove-hop-by-hop | | -|spring.cloud.gateway.filter.remove-hop-by-hop.headers | | +|spring.cloud.gateway.filter.remove-hop-by-hop | | +|spring.cloud.gateway.filter.remove-hop-by-hop.headers | | |spring.cloud.gateway.filter.remove-hop-by-hop.order | `+++0+++` | |spring.cloud.gateway.filter.remove-request-header.enabled | `+++true+++` | Enables the remove-request-header filter. |spring.cloud.gateway.filter.remove-request-parameter.enabled | `+++true+++` | Enables the remove-request-parameter filter. |spring.cloud.gateway.filter.remove-response-header.enabled | `+++true+++` | Enables the remove-response-header filter. |spring.cloud.gateway.filter.request-header-size.enabled | `+++true+++` | Enables the request-header-size filter. |spring.cloud.gateway.filter.request-header-to-request-uri.enabled | `+++true+++` | Enables the request-header-to-request-uri filter. -|spring.cloud.gateway.filter.request-rate-limiter | | -|spring.cloud.gateway.filter.request-rate-limiter.default-key-resolver | | +|spring.cloud.gateway.filter.request-rate-limiter | | +|spring.cloud.gateway.filter.request-rate-limiter.default-key-resolver | | |spring.cloud.gateway.filter.request-rate-limiter.default-rate-limiter | | |spring.cloud.gateway.filter.request-rate-limiter.enabled | `+++true+++` | Enables the request-rate-limiter filter. |spring.cloud.gateway.filter.request-size.enabled | `+++true+++` | Enables the request-size filter. @@ -53,18 +53,18 @@ |spring.cloud.gateway.filter.rewrite-request-parameter.enabled | `+++true+++` | Enables the rewrite-request-parameter filter. |spring.cloud.gateway.filter.rewrite-response-header.enabled | `+++true+++` | Enables the rewrite-response-header filter. |spring.cloud.gateway.filter.save-session.enabled | `+++true+++` | Enables the save-session filter. -|spring.cloud.gateway.filter.secure-headers | | -|spring.cloud.gateway.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | +|spring.cloud.gateway.filter.secure-headers | | +|spring.cloud.gateway.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | |spring.cloud.gateway.filter.secure-headers.content-type-options | `+++nosniff+++` | -|spring.cloud.gateway.filter.secure-headers.default-headers | | -|spring.cloud.gateway.filter.secure-headers.disable | | -|spring.cloud.gateway.filter.secure-headers.disabled-headers | | -|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | +|spring.cloud.gateway.filter.secure-headers.default-headers | | +|spring.cloud.gateway.filter.secure-headers.disable | | +|spring.cloud.gateway.filter.secure-headers.disabled-headers | | +|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | |spring.cloud.gateway.filter.secure-headers.enabled | `+++true+++` | Enables the secure-headers filter. -|spring.cloud.gateway.filter.secure-headers.enabled-headers | | -|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | -|spring.cloud.gateway.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | -|spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | +|spring.cloud.gateway.filter.secure-headers.enabled-headers | | +|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | +|spring.cloud.gateway.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | +|spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | |spring.cloud.gateway.filter.secure-headers.referrer-policy | `+++no-referrer+++` | |spring.cloud.gateway.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | |spring.cloud.gateway.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | @@ -87,16 +87,16 @@ |spring.cloud.gateway.global-filter.remove-cached-body.enabled | `+++true+++` | Enables the remove-cached-body global filter. |spring.cloud.gateway.global-filter.route-to-request-url.enabled | `+++true+++` | Enables the route-to-request-url global filter. |spring.cloud.gateway.global-filter.websocket-routing.enabled | `+++true+++` | Enables the websocket-routing global filter. -|spring.cloud.gateway.globalcors | | +|spring.cloud.gateway.globalcors | | |spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping | `+++false+++` | If global CORS config should be added to the URL handler. |spring.cloud.gateway.globalcors.cors-configurations | | |spring.cloud.gateway.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. -|spring.cloud.gateway.httpclient | | +|spring.cloud.gateway.httpclient | | |spring.cloud.gateway.httpclient.compression | `+++false+++` | Enables compression for Netty HttpClient. |spring.cloud.gateway.httpclient.connect-timeout | | The connect timeout in millis, the default is 30s. |spring.cloud.gateway.httpclient.max-header-size | | The max response header size. |spring.cloud.gateway.httpclient.max-initial-line-length | | The max initial line length. -|spring.cloud.gateway.httpclient.pool | | +|spring.cloud.gateway.httpclient.pool | | |spring.cloud.gateway.httpclient.pool.acquire-timeout | | Only for type FIXED, the maximum time in millis to wait for acquiring. |spring.cloud.gateway.httpclient.pool.eviction-interval | `+++0+++` | Perform regular eviction checks in the background at a specified interval. Disabled by default ({@link Duration#ZERO}) |spring.cloud.gateway.httpclient.pool.leasing-strategy | `+++fifo+++` | Configures the leasing strategy for the pool (fifo or lifo), defaults to FIFO which is Netty's default. @@ -106,7 +106,7 @@ |spring.cloud.gateway.httpclient.pool.metrics | `+++false+++` | Enables channel pools metrics to be collected and registered in Micrometer. Disabled by default. |spring.cloud.gateway.httpclient.pool.name | `+++proxy+++` | The channel pool map name, defaults to proxy. |spring.cloud.gateway.httpclient.pool.type | `+++elastic+++` | Type of pool for HttpClient to use (elastic, fixed or disabled). -|spring.cloud.gateway.httpclient.proxy | | +|spring.cloud.gateway.httpclient.proxy | | |spring.cloud.gateway.httpclient.proxy.host | | Hostname for proxy configuration of Netty HttpClient. |spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern | | Regular expression (Java) for a configured list of hosts. that should be reached directly, bypassing the proxy |spring.cloud.gateway.httpclient.proxy.password | | Password for proxy configuration of Netty HttpClient. @@ -114,7 +114,7 @@ |spring.cloud.gateway.httpclient.proxy.type | `+++http+++` | proxyType for proxy configuration of Netty HttpClient (http, socks4 or socks5). |spring.cloud.gateway.httpclient.proxy.username | | Username for proxy configuration of Netty HttpClient. |spring.cloud.gateway.httpclient.response-timeout | | The response timeout. -|spring.cloud.gateway.httpclient.ssl | | +|spring.cloud.gateway.httpclient.ssl | | |spring.cloud.gateway.httpclient.ssl.close-notify-flush-timeout | `+++3000ms+++` | SSL close_notify flush timeout. Default to 3000 ms. |spring.cloud.gateway.httpclient.ssl.close-notify-read-timeout | `+++0+++` | SSL close_notify read timeout. Default to 0 ms. |spring.cloud.gateway.httpclient.ssl.handshake-timeout | `+++10000ms+++` | SSL handshake timeout. Default to 10000 ms @@ -126,14 +126,14 @@ |spring.cloud.gateway.httpclient.ssl.ssl-bundle | | The name of the SSL bundle to use. |spring.cloud.gateway.httpclient.ssl.trusted-x509-certificates | | Trusted certificates for verifying the remote endpoint's certificate. |spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager | `+++false+++` | Installs the netty InsecureTrustManagerFactory. This is insecure and not suitable for production. -|spring.cloud.gateway.httpclient.websocket | | +|spring.cloud.gateway.httpclient.websocket | | |spring.cloud.gateway.httpclient.websocket.max-frame-payload-length | | Max frame payload length. |spring.cloud.gateway.httpclient.websocket.proxy-ping | `+++true+++` | Proxy ping frames to downstream services, defaults to true. |spring.cloud.gateway.httpclient.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpClient. |spring.cloud.gateway.httpserver.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpServer. -|spring.cloud.gateway.loadbalancer | | -|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | -|spring.cloud.gateway.metrics | | +|spring.cloud.gateway.loadbalancer | | +|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | +|spring.cloud.gateway.metrics | | |spring.cloud.gateway.metrics.enabled | `+++false+++` | Enables the collection of metrics data. |spring.cloud.gateway.metrics.prefix | `+++spring.cloud.gateway+++` | The prefix of all metrics emitted by gateway. |spring.cloud.gateway.metrics.tags | | Tags map that added to metrics. @@ -152,7 +152,7 @@ |spring.cloud.gateway.mvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.mvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. -|spring.cloud.gateway.mvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. +|spring.cloud.gateway.mvc.trusted-proxies | `+++true+++` | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.mvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -182,7 +182,7 @@ |spring.cloud.gateway.predicate.remote-addr.enabled | `+++true+++` | Enables the remote-addr predicate. |spring.cloud.gateway.predicate.weight.enabled | `+++true+++` | Enables the weight predicate. |spring.cloud.gateway.predicate.xforwarded-remote-addr.enabled | `+++true+++` | Enables the xforwarded-remote-addr predicate. -|spring.cloud.gateway.redis-rate-limiter | | +|spring.cloud.gateway.redis-rate-limiter | | |spring.cloud.gateway.redis-rate-limiter.burst-capacity-header | `+++X-RateLimit-Burst-Capacity+++` | The name of the header that returns the burst capacity configuration. |spring.cloud.gateway.redis-rate-limiter.config | | |spring.cloud.gateway.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. @@ -196,10 +196,10 @@ |spring.cloud.gateway.routes | | List of Routes. |spring.cloud.gateway.server.webflux.default-filters | | List of filter definitions that are applied to every route. |spring.cloud.gateway.server.webflux.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. -|spring.cloud.gateway.server.webflux.discovery.locator.filters | | +|spring.cloud.gateway.server.webflux.discovery.locator.filters | | |spring.cloud.gateway.server.webflux.discovery.locator.include-expression | `+++true+++` | SpEL expression that will evaluate whether to include a service in gateway integration or not, defaults to: true. |spring.cloud.gateway.server.webflux.discovery.locator.lower-case-service-id | `+++false+++` | Option to lower case serviceId in predicates and filters, defaults to false. Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/** -|spring.cloud.gateway.server.webflux.discovery.locator.predicates | | +|spring.cloud.gateway.server.webflux.discovery.locator.predicates | | |spring.cloud.gateway.server.webflux.discovery.locator.route-id-prefix | | The prefix for the routeId, defaults to discoveryClient.getClass().getSimpleName() + "_". Service Id will be appended to create the routeId. |spring.cloud.gateway.server.webflux.discovery.locator.url-expression | `+++'lb://'+serviceId+++` | SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId. |spring.cloud.gateway.server.webflux.enabled | `+++true+++` | Enables gateway functionality. @@ -213,7 +213,7 @@ |spring.cloud.gateway.server.webflux.filter.hystrix.enabled | `+++true+++` | Enables the hystrix filter. |spring.cloud.gateway.server.webflux.filter.json-to-grpc.enabled | `+++true+++` | Enables the JSON to gRPC filter. |spring.cloud.gateway.server.webflux.filter.local-response-cache.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.server.webflux.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|spring.cloud.gateway.server.webflux.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | |spring.cloud.gateway.server.webflux.filter.local-response-cache.size | | Maximum size of the cache to evict entries for this route (in KB, MB and GB). |spring.cloud.gateway.server.webflux.filter.local-response-cache.time-to-live | `+++5m+++` | Time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours). |spring.cloud.gateway.server.webflux.filter.map-request-header.enabled | `+++true+++` | Enables the map-request-header filter. @@ -222,15 +222,15 @@ |spring.cloud.gateway.server.webflux.filter.prefix-path.enabled | `+++true+++` | Enables the prefix-path filter. |spring.cloud.gateway.server.webflux.filter.preserve-host-header.enabled | `+++true+++` | Enables the preserve-host-header filter. |spring.cloud.gateway.server.webflux.filter.redirect-to.enabled | `+++true+++` | Enables the redirect-to filter. -|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.headers | | -|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.order | `+++0+++` | +|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.headers | | +|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.order | `+++0+++` | |spring.cloud.gateway.server.webflux.filter.remove-request-header.enabled | `+++true+++` | Enables the remove-request-header filter. |spring.cloud.gateway.server.webflux.filter.remove-request-parameter.enabled | `+++true+++` | Enables the remove-request-parameter filter. |spring.cloud.gateway.server.webflux.filter.remove-response-header.enabled | `+++true+++` | Enables the remove-response-header filter. |spring.cloud.gateway.server.webflux.filter.request-header-size.enabled | `+++true+++` | Enables the request-header-size filter. |spring.cloud.gateway.server.webflux.filter.request-header-to-request-uri.enabled | `+++true+++` | Enables the request-header-to-request-uri filter. -|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-key-resolver | | -|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-rate-limiter | | +|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-key-resolver | | +|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-rate-limiter | | |spring.cloud.gateway.server.webflux.filter.request-rate-limiter.enabled | `+++true+++` | Enables the request-rate-limiter filter. |spring.cloud.gateway.server.webflux.filter.request-size.enabled | `+++true+++` | Enables the request-size filter. |spring.cloud.gateway.server.webflux.filter.retry.enabled | `+++true+++` | Enables the retry filter. @@ -240,20 +240,20 @@ |spring.cloud.gateway.server.webflux.filter.rewrite-request-parameter.enabled | `+++true+++` | Enables the rewrite-request-parameter filter. |spring.cloud.gateway.server.webflux.filter.rewrite-response-header.enabled | `+++true+++` | Enables the rewrite-response-header filter. |spring.cloud.gateway.server.webflux.filter.save-session.enabled | `+++true+++` | Enables the save-session filter. -|spring.cloud.gateway.server.webflux.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.content-type-options | `+++nosniff+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.default-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.disable | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.disabled-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.download-options | `+++noopen+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.content-type-options | `+++nosniff+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.default-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.disable | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.disabled-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.download-options | `+++noopen+++` | |spring.cloud.gateway.server.webflux.filter.secure-headers.enabled | `+++true+++` | Enables the secure-headers filter. -|spring.cloud.gateway.server.webflux.filter.secure-headers.enabled-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.frame-options | `+++DENY+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.referrer-policy | `+++no-referrer+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.enabled-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.frame-options | `+++DENY+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.referrer-policy | `+++no-referrer+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | |spring.cloud.gateway.server.webflux.filter.set-path.enabled | `+++true+++` | Enables the set-path filter. |spring.cloud.gateway.server.webflux.filter.set-request-header.enabled | `+++true+++` | Enables the set-request-header filter. |spring.cloud.gateway.server.webflux.filter.set-request-host-header.enabled | `+++true+++` | Enables the set-request-host-header filter. @@ -274,7 +274,7 @@ |spring.cloud.gateway.server.webflux.global-filter.route-to-request-url.enabled | `+++true+++` | Enables the route-to-request-url global filter. |spring.cloud.gateway.server.webflux.global-filter.websocket-routing.enabled | `+++true+++` | Enables the websocket-routing global filter. |spring.cloud.gateway.server.webflux.globalcors.add-to-simple-url-handler-mapping | `+++false+++` | If global CORS config should be added to the URL handler. -|spring.cloud.gateway.server.webflux.globalcors.cors-configurations | | +|spring.cloud.gateway.server.webflux.globalcors.cors-configurations | | |spring.cloud.gateway.server.webflux.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. |spring.cloud.gateway.server.webflux.httpclient.compression | `+++false+++` | Enables compression for Netty HttpClient. |spring.cloud.gateway.server.webflux.httpclient.connect-timeout | | The connect timeout in millis, the default is 30s. @@ -311,7 +311,7 @@ |spring.cloud.gateway.server.webflux.httpclient.websocket.proxy-ping | `+++true+++` | Proxy ping frames to downstream services, defaults to true. |spring.cloud.gateway.server.webflux.httpclient.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpClient. |spring.cloud.gateway.server.webflux.httpserver.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpServer. -|spring.cloud.gateway.server.webflux.loadbalancer.use404 | `+++false+++` | +|spring.cloud.gateway.server.webflux.loadbalancer.use404 | `+++false+++` | |spring.cloud.gateway.server.webflux.metrics.enabled | `+++false+++` | Enables the collection of metrics data. |spring.cloud.gateway.server.webflux.metrics.prefix | `+++spring.cloud.gateway+++` | The prefix of all metrics emitted by gateway. |spring.cloud.gateway.server.webflux.metrics.tags | | Tags map that added to metrics. @@ -332,7 +332,7 @@ |spring.cloud.gateway.server.webflux.predicate.weight.enabled | `+++true+++` | Enables the weight predicate. |spring.cloud.gateway.server.webflux.predicate.xforwarded-remote-addr.enabled | `+++true+++` | Enables the xforwarded-remote-addr predicate. |spring.cloud.gateway.server.webflux.redis-rate-limiter.burst-capacity-header | `+++X-RateLimit-Burst-Capacity+++` | The name of the header that returns the burst capacity configuration. -|spring.cloud.gateway.server.webflux.redis-rate-limiter.config | | +|spring.cloud.gateway.server.webflux.redis-rate-limiter.config | | |spring.cloud.gateway.server.webflux.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. |spring.cloud.gateway.server.webflux.redis-rate-limiter.remaining-header | `+++X-RateLimit-Remaining+++` | The name of the header that returns number of remaining requests during the current second. |spring.cloud.gateway.server.webflux.redis-rate-limiter.replenish-rate-header | `+++X-RateLimit-Replenish-Rate+++` | The name of the header that returns the replenish rate configuration. @@ -343,7 +343,8 @@ |spring.cloud.gateway.server.webflux.route-refresh-listener.enabled | `+++true+++` | If RouteRefreshListener should be turned on. |spring.cloud.gateway.server.webflux.routes | | List of Routes. |spring.cloud.gateway.server.webflux.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. -|spring.cloud.gateway.server.webflux.streaming-media-types | | +|spring.cloud.gateway.server.webflux.streaming-media-types | | +|spring.cloud.gateway.server.webflux.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.server.webflux.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.server.webflux.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.server.webflux.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. @@ -371,6 +372,7 @@ |spring.cloud.gateway.server.webmvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.server.webmvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.server.webmvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. +|spring.cloud.gateway.server.webmvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.server.webmvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -384,10 +386,11 @@ |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.prefix-enabled | `+++true+++` | If X-Forwarded-Prefix is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-append | `+++true+++` | If appending X-Forwarded-Proto as a list is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-enabled | `+++true+++` | If X-Forwarded-Proto is enabled. -|spring.cloud.gateway.set-status | | +|spring.cloud.gateway.set-status | | |spring.cloud.gateway.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. |spring.cloud.gateway.streaming-media-types | | -|spring.cloud.gateway.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. +|spring.cloud.gateway.trusted-proxies | `+++true+++` | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. +|spring.cloud.gateway.x-forwarded | | |spring.cloud.gateway.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. diff --git a/docs/pom.xml b/docs/pom.xml index 709dc57e..3cfa608e 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index d1c8473c..e6ddefd0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.3.0-SNAPSHOT + 4.3.0 @@ -55,10 +55,10 @@ 1.0.8.RELEASE 17 2.3.0 - 3.3.0-SNAPSHOT - 4.3.0-SNAPSHOT - 4.3.0-SNAPSHOT - 4.3.0-SNAPSHOT + 3.3.0 + 4.3.0 + 4.3.0 + 4.3.0 diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 66103cf7..4c3d069a 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -6,12 +6,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 4.3.0-SNAPSHOT + 4.3.0 spring-cloud-gateway-dependencies - 4.3.0-SNAPSHOT + 4.3.0 pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index 7fb5e368..9c8fb3ca 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 49e2de46..7e6d670e 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index f10b23de..be171a9d 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 810172ab..4eeac491 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index 6c0074b1..07f7b67c 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index e339f496..93dce642 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-proxyexchange-webflux/pom.xml b/spring-cloud-gateway-proxyexchange-webflux/pom.xml index 3243a645..b87496f3 100644 --- a/spring-cloud-gateway-proxyexchange-webflux/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-proxyexchange-webflux diff --git a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml index 8d04d069..766243ee 100644 --- a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-proxyexchange-webmvc diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 20671002..093c666a 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index 01c47d60..ad1b7f0e 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server-webflux/pom.xml b/spring-cloud-gateway-server-webflux/pom.xml index 4f9f40e0..7bbdfa1f 100644 --- a/spring-cloud-gateway-server-webflux/pom.xml +++ b/spring-cloud-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-server-webflux diff --git a/spring-cloud-gateway-server-webmvc/pom.xml b/spring-cloud-gateway-server-webmvc/pom.xml index 9792dfe9..b9280fa4 100644 --- a/spring-cloud-gateway-server-webmvc/pom.xml +++ b/spring-cloud-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-server-webmvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 6430185a..74d0e48d 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index c74106d3..df9c575a 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 8e66ee4e..5702f708 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway-server-webflux/pom.xml b/spring-cloud-starter-gateway-server-webflux/pom.xml index ed3b79c4..27d20447 100644 --- a/spring-cloud-starter-gateway-server-webflux/pom.xml +++ b/spring-cloud-starter-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-starter-gateway-server-webflux diff --git a/spring-cloud-starter-gateway-server-webmvc/pom.xml b/spring-cloud-starter-gateway-server-webmvc/pom.xml index 14b339e1..f245cbea 100644 --- a/spring-cloud-starter-gateway-server-webmvc/pom.xml +++ b/spring-cloud-starter-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-starter-gateway-server-webmvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 9705acd7..9042e9dd 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.0 .. spring-cloud-starter-gateway From be0a9071b5fa0e853793413f9ea59818cad1cd19 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Thu, 29 May 2025 01:50:28 +0000 Subject: [PATCH 16/20] Going back to snapshots --- docs/modules/ROOT/partials/_configprops.adoc | 115 +++++++++--------- docs/pom.xml | 2 +- pom.xml | 12 +- spring-cloud-gateway-dependencies/pom.xml | 4 +- .../grpc/pom.xml | 2 +- .../http2/pom.xml | 2 +- .../httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server-webflux/pom.xml | 2 +- spring-cloud-gateway-server-webmvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 22 files changed, 83 insertions(+), 86 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 087392fb..13231741 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -1,9 +1,9 @@ |=== |Name | Default | Description -|spring.cloud.gateway | | +|spring.cloud.gateway | | |spring.cloud.gateway.default-filters | | List of filter definitions that are applied to every route. -|spring.cloud.gateway.discovery.locator | | +|spring.cloud.gateway.discovery.locator | | |spring.cloud.gateway.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. |spring.cloud.gateway.discovery.locator.filters | | |spring.cloud.gateway.discovery.locator.include-expression | `+++true+++` | SpEL expression that will evaluate whether to include a service in gateway integration or not, defaults to: true. @@ -21,10 +21,10 @@ |spring.cloud.gateway.filter.fallback-headers.enabled | `+++true+++` | Enables the fallback-headers filter. |spring.cloud.gateway.filter.hystrix.enabled | `+++true+++` | Enables the hystrix filter. |spring.cloud.gateway.filter.json-to-grpc.enabled | `+++true+++` | Enables the JSON to gRPC filter. -|spring.cloud.gateway.filter.local-response-cache | | +|spring.cloud.gateway.filter.local-response-cache | | |spring.cloud.gateway.filter.local-response-cache.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.filter.local-response-cache.request | | -|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|spring.cloud.gateway.filter.local-response-cache.request | | +|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | |spring.cloud.gateway.filter.local-response-cache.size | | Maximum size of the cache to evict entries for this route (in KB, MB and GB). |spring.cloud.gateway.filter.local-response-cache.time-to-live | `+++5m+++` | Time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours). |spring.cloud.gateway.filter.map-request-header.enabled | `+++true+++` | Enables the map-request-header filter. @@ -33,16 +33,16 @@ |spring.cloud.gateway.filter.prefix-path.enabled | `+++true+++` | Enables the prefix-path filter. |spring.cloud.gateway.filter.preserve-host-header.enabled | `+++true+++` | Enables the preserve-host-header filter. |spring.cloud.gateway.filter.redirect-to.enabled | `+++true+++` | Enables the redirect-to filter. -|spring.cloud.gateway.filter.remove-hop-by-hop | | -|spring.cloud.gateway.filter.remove-hop-by-hop.headers | | +|spring.cloud.gateway.filter.remove-hop-by-hop | | +|spring.cloud.gateway.filter.remove-hop-by-hop.headers | | |spring.cloud.gateway.filter.remove-hop-by-hop.order | `+++0+++` | |spring.cloud.gateway.filter.remove-request-header.enabled | `+++true+++` | Enables the remove-request-header filter. |spring.cloud.gateway.filter.remove-request-parameter.enabled | `+++true+++` | Enables the remove-request-parameter filter. |spring.cloud.gateway.filter.remove-response-header.enabled | `+++true+++` | Enables the remove-response-header filter. |spring.cloud.gateway.filter.request-header-size.enabled | `+++true+++` | Enables the request-header-size filter. |spring.cloud.gateway.filter.request-header-to-request-uri.enabled | `+++true+++` | Enables the request-header-to-request-uri filter. -|spring.cloud.gateway.filter.request-rate-limiter | | -|spring.cloud.gateway.filter.request-rate-limiter.default-key-resolver | | +|spring.cloud.gateway.filter.request-rate-limiter | | +|spring.cloud.gateway.filter.request-rate-limiter.default-key-resolver | | |spring.cloud.gateway.filter.request-rate-limiter.default-rate-limiter | | |spring.cloud.gateway.filter.request-rate-limiter.enabled | `+++true+++` | Enables the request-rate-limiter filter. |spring.cloud.gateway.filter.request-size.enabled | `+++true+++` | Enables the request-size filter. @@ -53,18 +53,18 @@ |spring.cloud.gateway.filter.rewrite-request-parameter.enabled | `+++true+++` | Enables the rewrite-request-parameter filter. |spring.cloud.gateway.filter.rewrite-response-header.enabled | `+++true+++` | Enables the rewrite-response-header filter. |spring.cloud.gateway.filter.save-session.enabled | `+++true+++` | Enables the save-session filter. -|spring.cloud.gateway.filter.secure-headers | | -|spring.cloud.gateway.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | +|spring.cloud.gateway.filter.secure-headers | | +|spring.cloud.gateway.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | |spring.cloud.gateway.filter.secure-headers.content-type-options | `+++nosniff+++` | -|spring.cloud.gateway.filter.secure-headers.default-headers | | -|spring.cloud.gateway.filter.secure-headers.disable | | -|spring.cloud.gateway.filter.secure-headers.disabled-headers | | -|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | +|spring.cloud.gateway.filter.secure-headers.default-headers | | +|spring.cloud.gateway.filter.secure-headers.disable | | +|spring.cloud.gateway.filter.secure-headers.disabled-headers | | +|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | |spring.cloud.gateway.filter.secure-headers.enabled | `+++true+++` | Enables the secure-headers filter. -|spring.cloud.gateway.filter.secure-headers.enabled-headers | | -|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | -|spring.cloud.gateway.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | -|spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | +|spring.cloud.gateway.filter.secure-headers.enabled-headers | | +|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | +|spring.cloud.gateway.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | +|spring.cloud.gateway.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | |spring.cloud.gateway.filter.secure-headers.referrer-policy | `+++no-referrer+++` | |spring.cloud.gateway.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | |spring.cloud.gateway.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | @@ -87,16 +87,16 @@ |spring.cloud.gateway.global-filter.remove-cached-body.enabled | `+++true+++` | Enables the remove-cached-body global filter. |spring.cloud.gateway.global-filter.route-to-request-url.enabled | `+++true+++` | Enables the route-to-request-url global filter. |spring.cloud.gateway.global-filter.websocket-routing.enabled | `+++true+++` | Enables the websocket-routing global filter. -|spring.cloud.gateway.globalcors | | +|spring.cloud.gateway.globalcors | | |spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping | `+++false+++` | If global CORS config should be added to the URL handler. |spring.cloud.gateway.globalcors.cors-configurations | | |spring.cloud.gateway.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. -|spring.cloud.gateway.httpclient | | +|spring.cloud.gateway.httpclient | | |spring.cloud.gateway.httpclient.compression | `+++false+++` | Enables compression for Netty HttpClient. |spring.cloud.gateway.httpclient.connect-timeout | | The connect timeout in millis, the default is 30s. |spring.cloud.gateway.httpclient.max-header-size | | The max response header size. |spring.cloud.gateway.httpclient.max-initial-line-length | | The max initial line length. -|spring.cloud.gateway.httpclient.pool | | +|spring.cloud.gateway.httpclient.pool | | |spring.cloud.gateway.httpclient.pool.acquire-timeout | | Only for type FIXED, the maximum time in millis to wait for acquiring. |spring.cloud.gateway.httpclient.pool.eviction-interval | `+++0+++` | Perform regular eviction checks in the background at a specified interval. Disabled by default ({@link Duration#ZERO}) |spring.cloud.gateway.httpclient.pool.leasing-strategy | `+++fifo+++` | Configures the leasing strategy for the pool (fifo or lifo), defaults to FIFO which is Netty's default. @@ -106,7 +106,7 @@ |spring.cloud.gateway.httpclient.pool.metrics | `+++false+++` | Enables channel pools metrics to be collected and registered in Micrometer. Disabled by default. |spring.cloud.gateway.httpclient.pool.name | `+++proxy+++` | The channel pool map name, defaults to proxy. |spring.cloud.gateway.httpclient.pool.type | `+++elastic+++` | Type of pool for HttpClient to use (elastic, fixed or disabled). -|spring.cloud.gateway.httpclient.proxy | | +|spring.cloud.gateway.httpclient.proxy | | |spring.cloud.gateway.httpclient.proxy.host | | Hostname for proxy configuration of Netty HttpClient. |spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern | | Regular expression (Java) for a configured list of hosts. that should be reached directly, bypassing the proxy |spring.cloud.gateway.httpclient.proxy.password | | Password for proxy configuration of Netty HttpClient. @@ -114,7 +114,7 @@ |spring.cloud.gateway.httpclient.proxy.type | `+++http+++` | proxyType for proxy configuration of Netty HttpClient (http, socks4 or socks5). |spring.cloud.gateway.httpclient.proxy.username | | Username for proxy configuration of Netty HttpClient. |spring.cloud.gateway.httpclient.response-timeout | | The response timeout. -|spring.cloud.gateway.httpclient.ssl | | +|spring.cloud.gateway.httpclient.ssl | | |spring.cloud.gateway.httpclient.ssl.close-notify-flush-timeout | `+++3000ms+++` | SSL close_notify flush timeout. Default to 3000 ms. |spring.cloud.gateway.httpclient.ssl.close-notify-read-timeout | `+++0+++` | SSL close_notify read timeout. Default to 0 ms. |spring.cloud.gateway.httpclient.ssl.handshake-timeout | `+++10000ms+++` | SSL handshake timeout. Default to 10000 ms @@ -126,14 +126,14 @@ |spring.cloud.gateway.httpclient.ssl.ssl-bundle | | The name of the SSL bundle to use. |spring.cloud.gateway.httpclient.ssl.trusted-x509-certificates | | Trusted certificates for verifying the remote endpoint's certificate. |spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager | `+++false+++` | Installs the netty InsecureTrustManagerFactory. This is insecure and not suitable for production. -|spring.cloud.gateway.httpclient.websocket | | +|spring.cloud.gateway.httpclient.websocket | | |spring.cloud.gateway.httpclient.websocket.max-frame-payload-length | | Max frame payload length. |spring.cloud.gateway.httpclient.websocket.proxy-ping | `+++true+++` | Proxy ping frames to downstream services, defaults to true. |spring.cloud.gateway.httpclient.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpClient. |spring.cloud.gateway.httpserver.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpServer. -|spring.cloud.gateway.loadbalancer | | -|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | -|spring.cloud.gateway.metrics | | +|spring.cloud.gateway.loadbalancer | | +|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | +|spring.cloud.gateway.metrics | | |spring.cloud.gateway.metrics.enabled | `+++false+++` | Enables the collection of metrics data. |spring.cloud.gateway.metrics.prefix | `+++spring.cloud.gateway+++` | The prefix of all metrics emitted by gateway. |spring.cloud.gateway.metrics.tags | | Tags map that added to metrics. @@ -152,7 +152,7 @@ |spring.cloud.gateway.mvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.mvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. -|spring.cloud.gateway.mvc.trusted-proxies | `+++true+++` | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. +|spring.cloud.gateway.mvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.mvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -182,7 +182,7 @@ |spring.cloud.gateway.predicate.remote-addr.enabled | `+++true+++` | Enables the remote-addr predicate. |spring.cloud.gateway.predicate.weight.enabled | `+++true+++` | Enables the weight predicate. |spring.cloud.gateway.predicate.xforwarded-remote-addr.enabled | `+++true+++` | Enables the xforwarded-remote-addr predicate. -|spring.cloud.gateway.redis-rate-limiter | | +|spring.cloud.gateway.redis-rate-limiter | | |spring.cloud.gateway.redis-rate-limiter.burst-capacity-header | `+++X-RateLimit-Burst-Capacity+++` | The name of the header that returns the burst capacity configuration. |spring.cloud.gateway.redis-rate-limiter.config | | |spring.cloud.gateway.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. @@ -196,10 +196,10 @@ |spring.cloud.gateway.routes | | List of Routes. |spring.cloud.gateway.server.webflux.default-filters | | List of filter definitions that are applied to every route. |spring.cloud.gateway.server.webflux.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. -|spring.cloud.gateway.server.webflux.discovery.locator.filters | | +|spring.cloud.gateway.server.webflux.discovery.locator.filters | | |spring.cloud.gateway.server.webflux.discovery.locator.include-expression | `+++true+++` | SpEL expression that will evaluate whether to include a service in gateway integration or not, defaults to: true. |spring.cloud.gateway.server.webflux.discovery.locator.lower-case-service-id | `+++false+++` | Option to lower case serviceId in predicates and filters, defaults to false. Useful with eureka when it automatically uppercases serviceId. so MYSERIVCE, would match /myservice/** -|spring.cloud.gateway.server.webflux.discovery.locator.predicates | | +|spring.cloud.gateway.server.webflux.discovery.locator.predicates | | |spring.cloud.gateway.server.webflux.discovery.locator.route-id-prefix | | The prefix for the routeId, defaults to discoveryClient.getClass().getSimpleName() + "_". Service Id will be appended to create the routeId. |spring.cloud.gateway.server.webflux.discovery.locator.url-expression | `+++'lb://'+serviceId+++` | SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId. |spring.cloud.gateway.server.webflux.enabled | `+++true+++` | Enables gateway functionality. @@ -213,7 +213,7 @@ |spring.cloud.gateway.server.webflux.filter.hystrix.enabled | `+++true+++` | Enables the hystrix filter. |spring.cloud.gateway.server.webflux.filter.json-to-grpc.enabled | `+++true+++` | Enables the JSON to gRPC filter. |spring.cloud.gateway.server.webflux.filter.local-response-cache.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.server.webflux.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|spring.cloud.gateway.server.webflux.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | |spring.cloud.gateway.server.webflux.filter.local-response-cache.size | | Maximum size of the cache to evict entries for this route (in KB, MB and GB). |spring.cloud.gateway.server.webflux.filter.local-response-cache.time-to-live | `+++5m+++` | Time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours). |spring.cloud.gateway.server.webflux.filter.map-request-header.enabled | `+++true+++` | Enables the map-request-header filter. @@ -222,15 +222,15 @@ |spring.cloud.gateway.server.webflux.filter.prefix-path.enabled | `+++true+++` | Enables the prefix-path filter. |spring.cloud.gateway.server.webflux.filter.preserve-host-header.enabled | `+++true+++` | Enables the preserve-host-header filter. |spring.cloud.gateway.server.webflux.filter.redirect-to.enabled | `+++true+++` | Enables the redirect-to filter. -|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.headers | | -|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.order | `+++0+++` | +|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.headers | | +|spring.cloud.gateway.server.webflux.filter.remove-hop-by-hop.order | `+++0+++` | |spring.cloud.gateway.server.webflux.filter.remove-request-header.enabled | `+++true+++` | Enables the remove-request-header filter. |spring.cloud.gateway.server.webflux.filter.remove-request-parameter.enabled | `+++true+++` | Enables the remove-request-parameter filter. |spring.cloud.gateway.server.webflux.filter.remove-response-header.enabled | `+++true+++` | Enables the remove-response-header filter. |spring.cloud.gateway.server.webflux.filter.request-header-size.enabled | `+++true+++` | Enables the request-header-size filter. |spring.cloud.gateway.server.webflux.filter.request-header-to-request-uri.enabled | `+++true+++` | Enables the request-header-to-request-uri filter. -|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-key-resolver | | -|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-rate-limiter | | +|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-key-resolver | | +|spring.cloud.gateway.server.webflux.filter.request-rate-limiter.default-rate-limiter | | |spring.cloud.gateway.server.webflux.filter.request-rate-limiter.enabled | `+++true+++` | Enables the request-rate-limiter filter. |spring.cloud.gateway.server.webflux.filter.request-size.enabled | `+++true+++` | Enables the request-size filter. |spring.cloud.gateway.server.webflux.filter.retry.enabled | `+++true+++` | Enables the retry filter. @@ -240,20 +240,20 @@ |spring.cloud.gateway.server.webflux.filter.rewrite-request-parameter.enabled | `+++true+++` | Enables the rewrite-request-parameter filter. |spring.cloud.gateway.server.webflux.filter.rewrite-response-header.enabled | `+++true+++` | Enables the rewrite-response-header filter. |spring.cloud.gateway.server.webflux.filter.save-session.enabled | `+++true+++` | Enables the save-session filter. -|spring.cloud.gateway.server.webflux.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.content-type-options | `+++nosniff+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.default-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.disable | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.disabled-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.download-options | `+++noopen+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.content-security-policy | `+++default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.content-type-options | `+++nosniff+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.default-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.disable | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.disabled-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.download-options | `+++noopen+++` | |spring.cloud.gateway.server.webflux.filter.secure-headers.enabled | `+++true+++` | Enables the secure-headers filter. -|spring.cloud.gateway.server.webflux.filter.secure-headers.enabled-headers | | -|spring.cloud.gateway.server.webflux.filter.secure-headers.frame-options | `+++DENY+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.referrer-policy | `+++no-referrer+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | -|spring.cloud.gateway.server.webflux.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.enabled-headers | | +|spring.cloud.gateway.server.webflux.filter.secure-headers.frame-options | `+++DENY+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.permissions-policy | `+++accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.permitted-cross-domain-policies | `+++none+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.referrer-policy | `+++no-referrer+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.strict-transport-security | `+++max-age=631138519+++` | +|spring.cloud.gateway.server.webflux.filter.secure-headers.xss-protection-header | `+++1 ; mode=block+++` | |spring.cloud.gateway.server.webflux.filter.set-path.enabled | `+++true+++` | Enables the set-path filter. |spring.cloud.gateway.server.webflux.filter.set-request-header.enabled | `+++true+++` | Enables the set-request-header filter. |spring.cloud.gateway.server.webflux.filter.set-request-host-header.enabled | `+++true+++` | Enables the set-request-host-header filter. @@ -274,7 +274,7 @@ |spring.cloud.gateway.server.webflux.global-filter.route-to-request-url.enabled | `+++true+++` | Enables the route-to-request-url global filter. |spring.cloud.gateway.server.webflux.global-filter.websocket-routing.enabled | `+++true+++` | Enables the websocket-routing global filter. |spring.cloud.gateway.server.webflux.globalcors.add-to-simple-url-handler-mapping | `+++false+++` | If global CORS config should be added to the URL handler. -|spring.cloud.gateway.server.webflux.globalcors.cors-configurations | | +|spring.cloud.gateway.server.webflux.globalcors.cors-configurations | | |spring.cloud.gateway.server.webflux.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. |spring.cloud.gateway.server.webflux.httpclient.compression | `+++false+++` | Enables compression for Netty HttpClient. |spring.cloud.gateway.server.webflux.httpclient.connect-timeout | | The connect timeout in millis, the default is 30s. @@ -311,7 +311,7 @@ |spring.cloud.gateway.server.webflux.httpclient.websocket.proxy-ping | `+++true+++` | Proxy ping frames to downstream services, defaults to true. |spring.cloud.gateway.server.webflux.httpclient.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpClient. |spring.cloud.gateway.server.webflux.httpserver.wiretap | `+++false+++` | Enables wiretap debugging for Netty HttpServer. -|spring.cloud.gateway.server.webflux.loadbalancer.use404 | `+++false+++` | +|spring.cloud.gateway.server.webflux.loadbalancer.use404 | `+++false+++` | |spring.cloud.gateway.server.webflux.metrics.enabled | `+++false+++` | Enables the collection of metrics data. |spring.cloud.gateway.server.webflux.metrics.prefix | `+++spring.cloud.gateway+++` | The prefix of all metrics emitted by gateway. |spring.cloud.gateway.server.webflux.metrics.tags | | Tags map that added to metrics. @@ -332,7 +332,7 @@ |spring.cloud.gateway.server.webflux.predicate.weight.enabled | `+++true+++` | Enables the weight predicate. |spring.cloud.gateway.server.webflux.predicate.xforwarded-remote-addr.enabled | `+++true+++` | Enables the xforwarded-remote-addr predicate. |spring.cloud.gateway.server.webflux.redis-rate-limiter.burst-capacity-header | `+++X-RateLimit-Burst-Capacity+++` | The name of the header that returns the burst capacity configuration. -|spring.cloud.gateway.server.webflux.redis-rate-limiter.config | | +|spring.cloud.gateway.server.webflux.redis-rate-limiter.config | | |spring.cloud.gateway.server.webflux.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. |spring.cloud.gateway.server.webflux.redis-rate-limiter.remaining-header | `+++X-RateLimit-Remaining+++` | The name of the header that returns number of remaining requests during the current second. |spring.cloud.gateway.server.webflux.redis-rate-limiter.replenish-rate-header | `+++X-RateLimit-Replenish-Rate+++` | The name of the header that returns the replenish rate configuration. @@ -343,8 +343,7 @@ |spring.cloud.gateway.server.webflux.route-refresh-listener.enabled | `+++true+++` | If RouteRefreshListener should be turned on. |spring.cloud.gateway.server.webflux.routes | | List of Routes. |spring.cloud.gateway.server.webflux.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. -|spring.cloud.gateway.server.webflux.streaming-media-types | | -|spring.cloud.gateway.server.webflux.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. +|spring.cloud.gateway.server.webflux.streaming-media-types | | |spring.cloud.gateway.server.webflux.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.server.webflux.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.server.webflux.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. @@ -372,7 +371,6 @@ |spring.cloud.gateway.server.webmvc.streaming-buffer-size | `+++16384+++` | Buffer size for streaming media mime-types. |spring.cloud.gateway.server.webmvc.streaming-media-types | | Mime-types that are streaming. |spring.cloud.gateway.server.webmvc.transfer-encoding-normalization-request-headers-filter.enabled | `+++true+++` | Enables the transfer-encoding-normalization-request-headers-filter. -|spring.cloud.gateway.server.webmvc.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded of X-Forwarded header. |spring.cloud.gateway.server.webmvc.weight-calculator-filter.enabled | `+++true+++` | Enables the weight-calculator-filter. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. @@ -386,11 +384,10 @@ |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.prefix-enabled | `+++true+++` | If X-Forwarded-Prefix is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-append | `+++true+++` | If appending X-Forwarded-Proto as a list is enabled. |spring.cloud.gateway.server.webmvc.x-forwarded-request-headers-filter.proto-enabled | `+++true+++` | If X-Forwarded-Proto is enabled. -|spring.cloud.gateway.set-status | | +|spring.cloud.gateway.set-status | | |spring.cloud.gateway.set-status.original-status-header-name | | The name of the header which contains http code of the proxied request. |spring.cloud.gateway.streaming-media-types | | -|spring.cloud.gateway.trusted-proxies | `+++true+++` | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. -|spring.cloud.gateway.x-forwarded | | +|spring.cloud.gateway.trusted-proxies | | Regular expression defining proxies that are trusted when they appear in a Forwarded or X-Forwarded header. |spring.cloud.gateway.x-forwarded.enabled | `+++true+++` | If the XForwardedHeadersFilter is enabled. |spring.cloud.gateway.x-forwarded.for-append | `+++true+++` | If appending X-Forwarded-For as a list is enabled. |spring.cloud.gateway.x-forwarded.for-enabled | `+++true+++` | If X-Forwarded-For is enabled. diff --git a/docs/pom.xml b/docs/pom.xml index 3cfa608e..709dc57e 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index e6ddefd0..d1c8473c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.3.0 + 4.3.0-SNAPSHOT @@ -55,10 +55,10 @@ 1.0.8.RELEASE 17 2.3.0 - 3.3.0 - 4.3.0 - 4.3.0 - 4.3.0 + 3.3.0-SNAPSHOT + 4.3.0-SNAPSHOT + 4.3.0-SNAPSHOT + 4.3.0-SNAPSHOT diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 4c3d069a..66103cf7 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -6,12 +6,12 @@ spring-cloud-dependencies-parent org.springframework.cloud - 4.3.0 + 4.3.0-SNAPSHOT spring-cloud-gateway-dependencies - 4.3.0 + 4.3.0-SNAPSHOT pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index 9c8fb3ca..7fb5e368 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 7e6d670e..49e2de46 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index be171a9d..f10b23de 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 4eeac491..810172ab 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index 07f7b67c..6c0074b1 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index 93dce642..e339f496 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-proxyexchange-webflux/pom.xml b/spring-cloud-gateway-proxyexchange-webflux/pom.xml index b87496f3..3243a645 100644 --- a/spring-cloud-gateway-proxyexchange-webflux/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-proxyexchange-webflux diff --git a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml index 766243ee..8d04d069 100644 --- a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-proxyexchange-webmvc diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 093c666a..20671002 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index ad1b7f0e..01c47d60 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server-webflux/pom.xml b/spring-cloud-gateway-server-webflux/pom.xml index 7bbdfa1f..4f9f40e0 100644 --- a/spring-cloud-gateway-server-webflux/pom.xml +++ b/spring-cloud-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-server-webflux diff --git a/spring-cloud-gateway-server-webmvc/pom.xml b/spring-cloud-gateway-server-webmvc/pom.xml index b9280fa4..9792dfe9 100644 --- a/spring-cloud-gateway-server-webmvc/pom.xml +++ b/spring-cloud-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-server-webmvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 74d0e48d..6430185a 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index df9c575a..c74106d3 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 5702f708..8e66ee4e 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway-server-webflux/pom.xml b/spring-cloud-starter-gateway-server-webflux/pom.xml index 27d20447..ed3b79c4 100644 --- a/spring-cloud-starter-gateway-server-webflux/pom.xml +++ b/spring-cloud-starter-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-starter-gateway-server-webflux diff --git a/spring-cloud-starter-gateway-server-webmvc/pom.xml b/spring-cloud-starter-gateway-server-webmvc/pom.xml index f245cbea..14b339e1 100644 --- a/spring-cloud-starter-gateway-server-webmvc/pom.xml +++ b/spring-cloud-starter-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-starter-gateway-server-webmvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 9042e9dd..9705acd7 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0 + 4.3.0-SNAPSHOT .. spring-cloud-starter-gateway From 019be9929446cdf9d7c66e5e2f02633b0ea0c34e Mon Sep 17 00:00:00 2001 From: spring-builds Date: Thu, 29 May 2025 01:50:29 +0000 Subject: [PATCH 17/20] Bumping versions to 4.3.1-SNAPSHOT after release --- docs/pom.xml | 2 +- pom.xml | 2 +- spring-cloud-gateway-dependencies/pom.xml | 2 +- spring-cloud-gateway-integration-tests/grpc/pom.xml | 2 +- spring-cloud-gateway-integration-tests/http2/pom.xml | 2 +- spring-cloud-gateway-integration-tests/httpclient/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- spring-cloud-gateway-integration-tests/pom.xml | 2 +- spring-cloud-gateway-mvc/pom.xml | 2 +- spring-cloud-gateway-proxyexchange-webflux/pom.xml | 2 +- spring-cloud-gateway-proxyexchange-webmvc/pom.xml | 2 +- spring-cloud-gateway-sample/pom.xml | 2 +- spring-cloud-gateway-server-mvc/pom.xml | 2 +- spring-cloud-gateway-server-webflux/pom.xml | 2 +- spring-cloud-gateway-server-webmvc/pom.xml | 2 +- spring-cloud-gateway-server/pom.xml | 2 +- spring-cloud-gateway-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-mvc/pom.xml | 2 +- spring-cloud-starter-gateway-server-webflux/pom.xml | 2 +- spring-cloud-starter-gateway-server-webmvc/pom.xml | 2 +- spring-cloud-starter-gateway/pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 709dc57e..83097fcc 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index d1c8473c..839495ef 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT pom Spring Cloud Gateway diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 66103cf7..92775dd9 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -11,7 +11,7 @@ spring-cloud-gateway-dependencies - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT pom spring-cloud-gateway-dependencies diff --git a/spring-cloud-gateway-integration-tests/grpc/pom.xml b/spring-cloud-gateway-integration-tests/grpc/pom.xml index 7fb5e368..bb1ac76d 100644 --- a/spring-cloud-gateway-integration-tests/grpc/pom.xml +++ b/spring-cloud-gateway-integration-tests/grpc/pom.xml @@ -18,7 +18,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index 49e2de46..ee87577b 100644 --- a/spring-cloud-gateway-integration-tests/http2/pom.xml +++ b/spring-cloud-gateway-integration-tests/http2/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/httpclient/pom.xml b/spring-cloud-gateway-integration-tests/httpclient/pom.xml index f10b23de..32aa3ae3 100644 --- a/spring-cloud-gateway-integration-tests/httpclient/pom.xml +++ b/spring-cloud-gateway-integration-tests/httpclient/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml index 810172ab..bab5a654 100644 --- a/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml +++ b/spring-cloud-gateway-integration-tests/mvc-failure-analyzer/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway-integration-tests - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index 6c0074b1..b2e3dc7a 100644 --- a/spring-cloud-gateway-integration-tests/pom.xml +++ b/spring-cloud-gateway-integration-tests/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index e339f496..feb0d076 100644 --- a/spring-cloud-gateway-mvc/pom.xml +++ b/spring-cloud-gateway-mvc/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-proxyexchange-webflux/pom.xml b/spring-cloud-gateway-proxyexchange-webflux/pom.xml index 3243a645..2f9f809b 100644 --- a/spring-cloud-gateway-proxyexchange-webflux/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-proxyexchange-webflux diff --git a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml index 8d04d069..3b833bb2 100644 --- a/spring-cloud-gateway-proxyexchange-webmvc/pom.xml +++ b/spring-cloud-gateway-proxyexchange-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-proxyexchange-webmvc diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 20671002..5cf2cbde 100644 --- a/spring-cloud-gateway-sample/pom.xml +++ b/spring-cloud-gateway-sample/pom.xml @@ -16,7 +16,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index 01c47d60..5203b300 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server-webflux/pom.xml b/spring-cloud-gateway-server-webflux/pom.xml index 4f9f40e0..2fd314ab 100644 --- a/spring-cloud-gateway-server-webflux/pom.xml +++ b/spring-cloud-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-server-webflux diff --git a/spring-cloud-gateway-server-webmvc/pom.xml b/spring-cloud-gateway-server-webmvc/pom.xml index 9792dfe9..0e81f0b1 100644 --- a/spring-cloud-gateway-server-webmvc/pom.xml +++ b/spring-cloud-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-server-webmvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 6430185a..9e576d2d 100644 --- a/spring-cloud-gateway-server/pom.xml +++ b/spring-cloud-gateway-server/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index c74106d3..b9fbcffb 100644 --- a/spring-cloud-gateway-webflux/pom.xml +++ b/spring-cloud-gateway-webflux/pom.xml @@ -11,7 +11,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 8e66ee4e..66b92a2d 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway-server-webflux/pom.xml b/spring-cloud-starter-gateway-server-webflux/pom.xml index ed3b79c4..da44d2f6 100644 --- a/spring-cloud-starter-gateway-server-webflux/pom.xml +++ b/spring-cloud-starter-gateway-server-webflux/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-starter-gateway-server-webflux diff --git a/spring-cloud-starter-gateway-server-webmvc/pom.xml b/spring-cloud-starter-gateway-server-webmvc/pom.xml index 14b339e1..e76833ed 100644 --- a/spring-cloud-starter-gateway-server-webmvc/pom.xml +++ b/spring-cloud-starter-gateway-server-webmvc/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-starter-gateway-server-webmvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 9705acd7..de0fee0a 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT .. spring-cloud-starter-gateway From 5ca9b9bf139322f22c4ddce2bc564c5b6441dd91 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Thu, 29 May 2025 01:51:31 +0000 Subject: [PATCH 18/20] Bumping dependency versions after release --- pom.xml | 10 +++++----- spring-cloud-gateway-dependencies/pom.xml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 839495ef..0895de20 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT @@ -55,10 +55,10 @@ 1.0.8.RELEASE 17 2.3.0 - 3.3.0-SNAPSHOT - 4.3.0-SNAPSHOT - 4.3.0-SNAPSHOT - 4.3.0-SNAPSHOT + 3.3.1-SNAPSHOT + 4.3.1-SNAPSHOT + 4.3.1-SNAPSHOT + 4.3.1-SNAPSHOT diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 92775dd9..44736442 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -6,7 +6,7 @@ spring-cloud-dependencies-parent org.springframework.cloud - 4.3.0-SNAPSHOT + 4.3.1-SNAPSHOT From 5460911e7db041da581ece0104efac3c7011d877 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 29 May 2025 15:29:44 +0200 Subject: [PATCH 19/20] Revert "Include interfaces for runtime hints scan." This reverts commit 738f2e8f7257d4989910f2f7d925d22bd1ed47e9. --- .../config/GatewayMvcRuntimeHintsProcessor.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java index 7635eb40..4691a19f 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java @@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.TypeReference; -import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution; import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; @@ -87,7 +86,7 @@ public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializatio private static Set> getTypesToRegister(String packageName) { Set> classesToAdd = new HashSet<>(); - ClassPathScanningCandidateComponentProvider provider = buildProvider(); + ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); provider.addIncludeFilter(new AssignableTypeFilter(Object.class)); provider.addExcludeFilter(new AssignableTypeFilter(FilterAutoConfiguration.class)); provider.addExcludeFilter(new AssignableTypeFilter(PredicateAutoConfiguration.class)); @@ -109,17 +108,6 @@ public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializatio return classesToAdd; } - private static ClassPathScanningCandidateComponentProvider buildProvider() { - return new ClassPathScanningCandidateComponentProvider(false) { - @SuppressWarnings("NullableProblems") - @Override - protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { - // Include both concrete classes and interfaces - return beanDefinition.getMetadata().isIndependent() && !beanDefinition.getMetadata().isAnnotation(); - } - }; - } - private static boolean shouldRegisterClass(Class clazz) { Set conditionClasses = beansConditionalOnClasses.getOrDefault(clazz.getName(), Collections.emptySet()); for (String conditionClass : conditionClasses) { From 43fe92f9fafa555cd15301214bce73bbc60eb066 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 29 May 2025 15:31:48 +0200 Subject: [PATCH 20/20] Fix MVC runtime hints. Signed-off-by: Olga Maciaszek-Sharma --- .../server/mvc/config/GatewayMvcRuntimeHintsProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java index 4691a19f..7dd037c6 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcRuntimeHintsProcessor.java @@ -33,6 +33,7 @@ import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContrib import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.cloud.gateway.server.mvc.filter.FilterFunctions; import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; import org.springframework.cloud.gateway.server.mvc.predicate.PredicateAutoConfiguration; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -75,7 +76,8 @@ public class GatewayMvcRuntimeHintsProcessor implements BeanFactoryInitializatio ReflectionHints hints = generationContext.getRuntimeHints().reflection(); Set> typesToRegister = Stream .of(getTypesToRegister(GATEWAY_MVC_FILTER_PACKAGE_NAME), - getTypesToRegister(GATEWAY_MVC_PREDICATE_PACKAGE_NAME), PROPERTIES) + getTypesToRegister(GATEWAY_MVC_PREDICATE_PACKAGE_NAME), PROPERTIES, + new HashSet<>(Collections.singletonList(FilterFunctions.class))) .flatMap(Set::stream) .collect(Collectors.toSet()); typesToRegister.forEach(clazz -> hints.registerType(TypeReference.of(clazz),