From c6ed8455579fd64ec15b9f56da6ec38f029531cb Mon Sep 17 00:00:00 2001 From: Stepan Mikhailiuk Date: Sun, 13 Apr 2025 22:11:33 +0800 Subject: [PATCH 01/15] feat(gateway-filter): add SetRequestUri gateway filter Signed-off-by: Stepan Mikhailiuk --- .../seturi-factory.adoc | 26 ++++ .../config/GatewayAutoConfiguration.java | 7 ++ .../SetRequestUriGatewayFilterFactory.java | 112 ++++++++++++++++++ .../route/builder/GatewayFilterSpec.java | 11 ++ ...iGatewayFilterFactoryIntegrationTests.java | 79 ++++++++++++ ...etRequestUriGatewayFilterFactoryTests.java | 83 +++++++++++++ .../cloud/gateway/test/AdhocTestSuite.java | 2 + 7 files changed, 320 insertions(+) create mode 100644 docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/gatewayfilter-factories/seturi-factory.adoc create mode 100644 spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java create mode 100644 spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryIntegrationTests.java create mode 100644 spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryTests.java diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/gatewayfilter-factories/seturi-factory.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/gatewayfilter-factories/seturi-factory.adoc new file mode 100644 index 00000000..2251d13b --- /dev/null +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webflux/gatewayfilter-factories/seturi-factory.adoc @@ -0,0 +1,26 @@ +[[seturi-gatewayfilter-factory]] += `SetRequestUri` `GatewayFilter` Factory + +The `SetRequestUri` `GatewayFilter` factory takes a `uri` parameter. +It offers a simple way to manipulate the request uri by allowing templated segments of the path. +This uses the URI templates from Spring Framework. +Multiple matching segments are allowed. +The following listing configures a `SetRequestUri` `GatewayFilter`: + +.application.yml +[source,yaml] +---- +spring: + cloud: + gateway: + routes: + - id: seturi_route + uri: no://op + predicates: + - Path=/{appId}/** + filters: + - SetRequestUri=http://{appId}.example.com +---- + +For a request path of `/red-application/blue`, this sets the uri to `http://red-application.example.com` before making the downstream request and the final url, including path is going to be `http://red-application.example.com/red-application/blue` + 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 5d399d95..60108fa6 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 @@ -110,6 +110,7 @@ import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties; import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetRequestHostHeaderGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.SetRequestUriGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory; @@ -718,6 +719,12 @@ public class GatewayAutoConfiguration { return new RequestHeaderToRequestUriGatewayFilterFactory(); } + @Bean + @ConditionalOnEnabledFilter + public SetRequestUriGatewayFilterFactory setRequestUriGatewayFilterFactory() { + return new SetRequestUriGatewayFilterFactory(); + } + @Bean @ConditionalOnEnabledFilter public RequestSizeGatewayFilterFactory requestSizeGatewayFilterFactory() { diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java new file mode 100644 index 00000000..2910d88d --- /dev/null +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java @@ -0,0 +1,112 @@ +/* + * Copyright 2013-2020 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.factory; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriComponentsBuilder; + +import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.getUriTemplateVariables; + +/** + * This filter changes the request uri. + * + * @author Stepan Mikhailiuk + */ +public class SetRequestUriGatewayFilterFactory + extends AbstractChangeRequestUriGatewayFilterFactory { + + private static final Logger log = LoggerFactory.getLogger(SetRequestUriGatewayFilterFactory.class); + + public SetRequestUriGatewayFilterFactory() { + super(Config.class); + } + + @Override + public List shortcutFieldOrder() { + return Arrays.asList(NAME_KEY); + } + + @Override + public GatewayFilter apply(Config config) { + // AbstractChangeRequestUriGatewayFilterFactory.apply() returns + // OrderedGatewayFilter + OrderedGatewayFilter gatewayFilter = (OrderedGatewayFilter) super.apply(config); + return new OrderedGatewayFilter(gatewayFilter, gatewayFilter.getOrder()) { + @Override + public String toString() { + return filterToStringCreator(SetRequestUriGatewayFilterFactory.this) + .append("template", config.getTemplate()) + .toString(); + } + }; + } + + String getUri(ServerWebExchange exchange, Config config) { + String template = config.getTemplate(); + + if (template.indexOf('{') == -1) { + return template; + } + + Map variables = getUriTemplateVariables(exchange); + return UriComponentsBuilder.fromUriString(template).build().expand(variables).toUriString(); + } + + @Override + protected Optional determineRequestUri(ServerWebExchange exchange, Config config) { + try { + String url = getUri(exchange, config); + URI uri = URI.create(url); + if (!uri.isAbsolute()) { + throw new IllegalArgumentException("URI is not absolute"); + } + return Optional.of(uri); + } + catch (IllegalArgumentException e) { + + log.info("Request url is invalid : url={}, error={}", config.getTemplate(), e.getMessage()); + return Optional.ofNullable(null); + } + } + + public static class Config { + + private String template; + + public String getTemplate() { + return template; + } + + public void setTemplate(String template) { + this.template = template; + } + + } + +} diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index 47723b74..8b87e45a 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -58,6 +58,7 @@ import org.springframework.cloud.gateway.filter.factory.RemoveRequestParameterGa import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestHeaderSizeGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory; +import org.springframework.cloud.gateway.filter.factory.SetRequestUriGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory; @@ -869,6 +870,16 @@ public class GatewayFilterSpec extends UriSpec { return filter(getBean(RequestHeaderToRequestUriGatewayFilterFactory.class).apply(c -> c.setName(headerName))); } + /** + * A filter which changes the URI the request will be routed to by the Gateway by + * pulling it from a header on the request. + * @param uri the URI + * @return a {@link GatewayFilterSpec} that can be used to apply additional filters + */ + public GatewayFilterSpec setRequestUri(String uri) { + return filter(getBean(SetRequestUriGatewayFilterFactory.class).apply(c -> c.setTemplate(uri))); + } + /** * A filter which change the URI the request will be routed to by the Gateway. * @param determineRequestUri a {@link Function} which takes a diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryIntegrationTests.java new file mode 100644 index 00000000..b52a81af --- /dev/null +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryIntegrationTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013-2020 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.factory; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; +import org.springframework.cloud.gateway.test.BaseWebClientTests; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; + +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * @author Stepan Mikhailiuk + */ +@SpringBootTest(webEnvironment = RANDOM_PORT) +@DirtiesContext +public class SetRequestUriGatewayFilterFactoryIntegrationTests extends BaseWebClientTests { + + @LocalServerPort + int port; + + @Test + public void setUriWorkWithProperties() { + testClient.get().uri("/").header("Host", "testservice.setrequesturi.org").exchange().expectStatus().isOk(); + + testClient.get() + .uri("/service/testservice") + .header("Host", "setrequesturi.org") + .exchange() + .expectStatus() + .isOk(); + } + + @EnableAutoConfiguration + @SpringBootConfiguration + @Import(DefaultTestConfig.class) + public static class TestConfig { + + @Bean + public RouteLocator routeLocator(RouteLocatorBuilder builder) { + return builder.routes() + .route("map_subdomain_to_service_name", + r -> r.host("{serviceName}.setrequesturi.org") + .filters(f -> f.prefixPath("/httpbin").setRequestUri("lb://{serviceName}")) + .uri("no://op")) + .route("map_path_to_service_name", + r -> r.host("setrequesturi.org") + .and() + .path("/service/{serviceName}") + .filters(f -> f.rewritePath("/.*", "/").setRequestUri("lb://{serviceName}")) + .uri("no://op")) + .build(); + } + + } + +} diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryTests.java new file mode 100644 index 00000000..2366b0c8 --- /dev/null +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactoryTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2013-2020 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.factory; + +import java.net.URI; + +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import reactor.core.publisher.Mono; + +import org.springframework.cloud.gateway.filter.GatewayFilter; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; +import org.springframework.web.server.ServerWebExchange; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; + +/** + * @author Stepan Mikhailiuk + */ +public class SetRequestUriGatewayFilterFactoryTests { + + @Test + public void filterChangeRequestUri() { + SetRequestUriGatewayFilterFactory factory = new SetRequestUriGatewayFilterFactory(); + GatewayFilter filter = factory.apply(c -> c.setTemplate("https://example.com")); + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost").build(); + ServerWebExchange exchange = MockServerWebExchange.from(request); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://localhost")); + GatewayFilterChain filterChain = mock(GatewayFilterChain.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(ServerWebExchange.class); + when(filterChain.filter(captor.capture())).thenReturn(Mono.empty()); + filter.filter(exchange, filterChain); + ServerWebExchange webExchange = captor.getValue(); + URI uri = (URI) webExchange.getAttributes().get(GATEWAY_REQUEST_URL_ATTR); + assertThat(uri).isNotNull(); + assertThat(uri.toString()).isEqualTo("https://example.com"); + } + + @Test + public void filterDoesNotChangeRequestUriIfUriIsInvalid() throws Exception { + SetRequestUriGatewayFilterFactory factory = new SetRequestUriGatewayFilterFactory(); + GatewayFilter filter = factory.apply(c -> c.setTemplate("invalid_uri")); + MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost").build(); + ServerWebExchange exchange = MockServerWebExchange.from(request); + exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("http://localhost")); + GatewayFilterChain filterChain = mock(GatewayFilterChain.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(ServerWebExchange.class); + when(filterChain.filter(captor.capture())).thenReturn(Mono.empty()); + filter.filter(exchange, filterChain); + ServerWebExchange webExchange = captor.getValue(); + URI uri = (URI) webExchange.getAttributes().get(GATEWAY_REQUEST_URL_ATTR); + assertThat(uri).isNotNull(); + assertThat(uri.toURL().toString()).isEqualTo("http://localhost"); + } + + @Test + public void toStringFormat() { + SetRequestUriGatewayFilterFactory.Config config = new SetRequestUriGatewayFilterFactory.Config(); + config.setTemplate("http://localhost:8080"); + GatewayFilter filter = new SetRequestUriGatewayFilterFactory().apply(config); + assertThat(filter.toString()).contains("http://localhost:8080"); + } + +} diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java index 38041174..bba39646 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/test/AdhocTestSuite.java @@ -66,6 +66,8 @@ import static org.junit.Assume.assumeThat; RewriteLocationResponseHeaderGatewayFilterFactoryTests.class, org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactoryTests.class, org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactoryIntegrationTests.class, + org.springframework.cloud.gateway.filter.factory.SetRequestUriGatewayFilterFactoryTests.class, + org.springframework.cloud.gateway.filter.factory.SetRequestUriGatewayFilterFactoryIntegrationTests.class, org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactoryTests.class, org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactoryTests.class, org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactoryIntegrationTests.class, From 98021b54c1fe8c11c71f16111ac63e7b0c8fbda2 Mon Sep 17 00:00:00 2001 From: raccoonback Date: Thu, 15 May 2025 00:08:42 +0900 Subject: [PATCH 02/15] Fix improper encoding of '+' in query parameter values in mvc Signed-off-by: raccoonback --- .../gateway/server/mvc/filter/BeforeFilterFunctions.java | 3 +-- .../gateway/server/mvc/filter/BeforeFilterFunctionsTests.java | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java index 3c86e394..98f0bbc8 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java @@ -45,7 +45,6 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriTemplate; -import org.springframework.web.util.UriUtils; import static org.springframework.cloud.gateway.server.mvc.common.MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR; import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap; @@ -216,7 +215,7 @@ public abstract class BeforeFilterFunctions { MultiValueMap queryParams = new LinkedMultiValueMap<>(request.params()); queryParams.remove(name); - MultiValueMap encodedQueryParams = UriUtils.encodeQueryParams(queryParams); + MultiValueMap encodedQueryParams = MvcUtils.encodeQueryParams(queryParams); // remove from uri URI newUri = UriComponentsBuilder.fromUri(request.uri()) diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java index a8777c56..c90b256c 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java @@ -119,6 +119,7 @@ class BeforeFilterFunctionsTests { MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/path") .queryParam("foo", "bar") .queryParam("baz[]", "qux[]") + .queryParam("quux", "corge+") .buildRequest(null); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); @@ -127,7 +128,8 @@ class BeforeFilterFunctionsTests { assertThat(result.param("foo")).isEmpty(); assertThat(result.param("baz[]")).isPresent().hasValue("qux[]"); - assertThat(result.uri().toString()).hasToString("http://localhost/path?baz%5B%5D=qux%5B%5D"); + assertThat(result.param("quux")).isPresent().hasValue("corge+"); + assertThat(result.uri().toString()).hasToString("http://localhost/path?baz%5B%5D=qux%5B%5D&quux=corge%2B"); } @Test From 330a43d63185f60b879f70c4d9cff43b541607ed Mon Sep 17 00:00:00 2001 From: raccoonback Date: Thu, 15 May 2025 08:32:24 +0900 Subject: [PATCH 03/15] Fix improper encoding of '+' in query parameter values Signed-off-by: raccoonback --- ...eRequestParameterGatewayFilterFactory.java | 5 +++-- ...eRequestParameterGatewayFilterFactory.java | 5 +++-- .../support/ServerWebExchangeUtils.java | 17 ++++++++++++++++ ...estParameterGatewayFilterFactoryTests.java | 20 +++++++++++++++++++ ...estParameterGatewayFilterFactoryTests.java | 6 ++++++ 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactory.java index 9d17f6ef..b8469337 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactory.java @@ -24,12 +24,12 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; -import org.springframework.web.util.UriUtils; import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap; @@ -59,7 +59,8 @@ public class RemoveRequestParameterGatewayFilterFactory queryParams.remove(config.getName()); try { - MultiValueMap encodedQueryParams = UriUtils.encodeQueryParams(queryParams); + MultiValueMap encodedQueryParams = ServerWebExchangeUtils + .encodeQueryParams(queryParams); URI newUri = UriComponentsBuilder.fromUri(request.getURI()) .replaceQueryParams(unmodifiableMultiValueMap(encodedQueryParams)) .build(true) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactory.java index 02bccdaf..18f5e588 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactory.java @@ -24,13 +24,13 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; -import org.springframework.web.util.UriUtils; import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator; import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap; @@ -71,7 +71,8 @@ public class RewriteRequestParameterGatewayFilterFactory } try { - MultiValueMap encodedQueryParams = UriUtils.encodeQueryParams(queryParams); + MultiValueMap encodedQueryParams = ServerWebExchangeUtils + .encodeQueryParams(queryParams); URI uri = uriComponentsBuilder.replaceQueryParams(unmodifiableMultiValueMap(encodedQueryParams)) .build(true) .toUri(); diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java index 7585a182..fd185504 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java @@ -17,9 +17,11 @@ package org.springframework.cloud.gateway.support; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -48,9 +50,13 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriUtils; /** * @author Spencer Gibb @@ -260,6 +266,17 @@ public final class ServerWebExchangeUtils { return encoded; } + public static MultiValueMap encodeQueryParams(MultiValueMap params) { + MultiValueMap encodedQueryParams = new LinkedMultiValueMap<>(params.size()); + for (Map.Entry> entry : params.entrySet()) { + for (String value : entry.getValue()) { + encodedQueryParams.add(UriUtils.encode(entry.getKey(), StandardCharsets.UTF_8), + UriUtils.encode(value, StandardCharsets.UTF_8)); + } + } + return CollectionUtils.unmodifiableMultiValueMap(encodedQueryParams); + } + public static HttpStatus parse(String statusString) { HttpStatus httpStatus; diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactoryTests.java index a96aef38..2eb96bb6 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RemoveRequestParameterGatewayFilterFactoryTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.gateway.filter.factory; +import java.net.URI; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -24,6 +26,7 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory.NameConfig; +import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -123,6 +126,23 @@ class RemoveRequestParameterGatewayFilterFactoryTests { assertThat(actualRequest.getQueryParams()).containsEntry("ccc", singletonList(",xyz")); } + @Test + void removeRequestParameterFilterShouldHandleRemainingPlusSignParams() { + MockServerHttpRequest request = MockServerHttpRequest + .method(HttpMethod.GET, URI.create("http://localhost?foo=bar&aaa=%2Bxyz")) + .build(); + exchange = MockServerWebExchange.from(request); + NameConfig config = new NameConfig(); + config.setName("foo"); + GatewayFilter filter = new RemoveRequestParameterGatewayFilterFactory().apply(config); + + filter.filter(exchange, filterChain); + + ServerHttpRequest actualRequest = captor.getValue().getRequest(); + assertThat(actualRequest.getQueryParams()).doesNotContainKey("foo"); + assertThat(actualRequest.getQueryParams()).containsEntry("aaa", singletonList("+xyz")); + } + @Test void removeRequestParameterFilterShouldHandleEncodedParameterName() { MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost") diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactoryTests.java index f7803861..24aa900b 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/RewriteRequestParameterGatewayFilterFactoryTests.java @@ -88,6 +88,12 @@ class RewriteRequestParameterGatewayFilterFactoryTests { Map.of("campaign[]", List.of("blue"), "color", List.of("white"))); } + @Test + void rewriteRequestParameterFilterWithPlusSign() { + testRewriteRequestParameterFilter("color", "white+", "campaign=blue%2B&color=green", + Map.of("campaign", List.of("blue+"), "color", List.of("white+"))); + } + private void testRewriteRequestParameterFilter(String name, String replacement, String query, Map> expectedQueryParams) { GatewayFilter filter = new RewriteRequestParameterGatewayFilterFactory() From c09f3831a0177160c0760cabec5b541a06c58fcd Mon Sep 17 00:00:00 2001 From: spring-builds Date: Fri, 16 May 2025 13:26:02 +0000 Subject: [PATCH 04/15] Bumping versions --- ...wayControllerEndpointRedisRefreshTest.java | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpointRedisRefreshTest.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpointRedisRefreshTest.java index 1d630bac..b2b331bf 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpointRedisRefreshTest.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/actuate/GatewayControllerEndpointRedisRefreshTest.java @@ -49,8 +49,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen /** * @author Peter Müller */ -@SpringBootTest(properties = {"management.endpoint.gateway.enabled=true", - "management.endpoints.web.exposure.include=*", "spring.cloud.gateway.actuator.verbose.enabled=true"}, +@SpringBootTest(properties = { "management.endpoint.gateway.enabled=true", + "management.endpoints.web.exposure.include=*", "spring.cloud.gateway.actuator.verbose.enabled=true" }, webEnvironment = RANDOM_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @ActiveProfiles("redis-route-repository") @@ -94,8 +94,9 @@ public class GatewayControllerEndpointRedisRefreshTest { createOrUpdateRouteWithCors(cors); Awaitility.await().atMost(Duration.ofSeconds(3)).untilAsserted(() -> assertRouteHasCorsConfig(cors)); - Awaitility.await().atMost(Duration.ofSeconds(3)) - .untilAsserted(() -> assertPreflightAllowOrigin("http://example.org")); + Awaitility.await() + .atMost(Duration.ofSeconds(3)) + .untilAsserted(() -> assertPreflightAllowOrigin("http://example.org")); } void createOrUpdateRouteWithCors(Map cors) { @@ -108,41 +109,41 @@ public class GatewayControllerEndpointRedisRefreshTest { testRouteDefinition.setMetadata(Map.of("cors", cors)); testClient.post() - .uri("http://localhost:" + port + "/actuator/gateway/routes/cors-test-route") - .accept(MediaType.APPLICATION_JSON) - .body(BodyInserters.fromValue(testRouteDefinition)) - .exchange() - .expectStatus() - .isCreated(); + .uri("http://localhost:" + port + "/actuator/gateway/routes/cors-test-route") + .accept(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(testRouteDefinition)) + .exchange() + .expectStatus() + .isCreated(); testClient.post() - .uri("http://localhost:" + port + "/actuator/gateway/refresh") - .exchange() - .expectStatus() - .isOk(); + .uri("http://localhost:" + port + "/actuator/gateway/refresh") + .exchange() + .expectStatus() + .isOk(); } void assertRouteHasCorsConfig(Map cors) { testClient.get() - .uri("http://localhost:" + port + "/actuator/gateway/routes/cors-test-route") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("$.metadata") - .value(map -> assertThat((Map) map).hasSize(1) - .containsEntry("cors", cors)); + .uri("http://localhost:" + port + "/actuator/gateway/routes/cors-test-route") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .jsonPath("$.metadata") + .value(map -> assertThat((Map) map).hasSize(1).containsEntry("cors", cors)); } void assertPreflightAllowOrigin(String origin) { testClient.options() - .uri("http://localhost:" + port + "/") - .header("Origin", "http://example.org") - .header("Access-Control-Request-Method", "GET") - .exchange() - .expectStatus() - .isOk() - .expectHeader() - .valueEquals("Access-Control-Allow-Origin", origin); + .uri("http://localhost:" + port + "/") + .header("Origin", "http://example.org") + .header("Access-Control-Request-Method", "GET") + .exchange() + .expectStatus() + .isOk() + .expectHeader() + .valueEquals("Access-Control-Allow-Origin", origin); } + } From 7b4dd7cc285d7f46b5f020b83cd8b0d93537cd40 Mon Sep 17 00:00:00 2001 From: Stepan Mikhailiuk Date: Tue, 20 May 2025 09:07:54 +0800 Subject: [PATCH 05/15] fix(*): remove unnecessary exception according review comments Signed-off-by: Stepan Mikhailiuk --- .../filter/factory/SetRequestUriGatewayFilterFactory.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java index 2910d88d..8f87428d 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java @@ -84,7 +84,8 @@ public class SetRequestUriGatewayFilterFactory String url = getUri(exchange, config); URI uri = URI.create(url); if (!uri.isAbsolute()) { - throw new IllegalArgumentException("URI is not absolute"); + log.info("Request url is invalid: url={}, error=URI is not absolute", url); + return Optional.ofNullable(null); } return Optional.of(uri); } From f5076c41ef5ec7fa92bf635c2735894201edb813 Mon Sep 17 00:00:00 2001 From: Stepan Mikhailiuk Date: Tue, 20 May 2025 09:08:13 +0800 Subject: [PATCH 06/15] fix(*): remove unnecessary exception according review comments Signed-off-by: Stepan Mikhailiuk --- .../filter/factory/SetRequestUriGatewayFilterFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java index 8f87428d..1fbdfaed 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SetRequestUriGatewayFilterFactory.java @@ -90,7 +90,6 @@ public class SetRequestUriGatewayFilterFactory return Optional.of(uri); } catch (IllegalArgumentException e) { - log.info("Request url is invalid : url={}, error={}", config.getTemplate(), e.getMessage()); return Optional.ofNullable(null); } From b5afd8883d9baa4c4eee6f42577aa2bfcac87856 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Tue, 20 May 2025 17:39:25 +0200 Subject: [PATCH 07/15] Add tests for LoadBalancerHandlerConfiguration (#3779) * Add autoconfiguration tests. Signed-off-by: Olga Maciaszek-Sharma --- ...atewayServerMvcAutoConfigurationTests.java | 25 +++++++- ...ServerMvcLoadBalancerIntegrationTests.java | 62 +++++++++++++++++++ .../src/test/resources/application-lb.yml | 11 ++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java create mode 100644 spring-cloud-gateway-server-mvc/src/test/resources/application-lb.yml diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java index 0eb0ff71..71e3e638 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2024 the original author or authors. + * 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. @@ -34,6 +34,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder; import org.springframework.boot.http.client.ClientHttpRequestFactorySettings; import org.springframework.boot.http.client.SimpleClientHttpRequestFactoryBuilder; +import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; import org.springframework.cloud.gateway.server.mvc.filter.FormFilter; @@ -47,6 +48,7 @@ import org.springframework.cloud.gateway.server.mvc.filter.WeightCalculatorFilte import org.springframework.cloud.gateway.server.mvc.filter.XForwardedRequestHeadersFilter; import org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctionAutoConfiguration; import org.springframework.cloud.gateway.server.mvc.predicate.PredicateAutoConfiguration; +import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; import org.springframework.context.ConfigurableApplicationContext; import static org.assertj.core.api.Assertions.assertThat; @@ -204,6 +206,27 @@ public class GatewayServerMvcAutoConfigurationTests { assertThat(builder).isInstanceOf(SimpleClientHttpRequestFactoryBuilder.class); } + @Test + void loadBalancerFunctionHandlerAdded() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, + HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, + HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, + RestClientAutoConfiguration.class)) + .run(context -> assertThat(context).hasBean("lbHandlerFunctionDefinition")); + } + + @Test + void loadBalancerFunctionHandlerNotAddedWhenNoLoadBalancerClientOnClasspath() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, + HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, + HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, + RestClientAutoConfiguration.class)) + .withClassLoader(new FilteredClassLoader(LoadBalancerClient.class)) + .run(context -> assertThat(context).doesNotHaveBean("lbHandlerFunctionDefinition")); + } + @SpringBootConfiguration @EnableAutoConfiguration static class TestConfig { diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java new file mode 100644 index 00000000..f0b91066 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java @@ -0,0 +1,62 @@ +/* + * 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; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.cloud.gateway.server.mvc.filter.FilterAutoConfiguration; +import org.springframework.cloud.gateway.server.mvc.test.HttpbinTestcontainers; +import org.springframework.cloud.gateway.server.mvc.test.TestLoadBalancerConfig; +import org.springframework.cloud.gateway.server.mvc.test.client.TestRestClient; +import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +/** + * Integration tests for {@link FilterAutoConfiguration.LoadBalancerHandlerConfiguration}. + * + * @author Olga Maciaszek-Sharma + * + */ +@SpringBootTest(classes = {ServerMvcLoadBalancerIntegrationTests.Config.class, FilterAutoConfiguration.class}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ContextConfiguration(initializers = HttpbinTestcontainers.class) +@ActiveProfiles("lb") +public class ServerMvcLoadBalancerIntegrationTests { + + @LocalServerPort + int port; + + @Autowired + TestRestClient testRestClient; + + @Test + void shouldUseLbHandlerFunctionDefinitionToResolveHost() { + testRestClient.get() + .uri("http://localhost:" + port + "/test") + .exchange().expectStatus().isOk(); + } + + @SpringBootApplication + @LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class) + static class Config { + } +} diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-lb.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-lb.yml new file mode 100644 index 00000000..9d0437b3 --- /dev/null +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-lb.yml @@ -0,0 +1,11 @@ +spring: + cloud: + gateway: + mvc: + routes: + - id: test + uri: lb://httpbin + predicates: + - Path=/test/** + filters: + - StripPrefix=1 \ No newline at end of file From b5f98411a91da0d5cf9cae41f628663dde186e0b Mon Sep 17 00:00:00 2001 From: spencergibb Date: Tue, 20 May 2025 13:28:20 -0400 Subject: [PATCH 08/15] Adds spring-boot-properties-migrator to server starters. This is temporary for backwards compatibility. --- spring-cloud-starter-gateway-mvc/pom.xml | 5 +++++ spring-cloud-starter-gateway-server-webflux/pom.xml | 5 +++++ spring-cloud-starter-gateway-server-webmvc/pom.xml | 5 +++++ spring-cloud-starter-gateway/pom.xml | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index e86d2d1f..8e66ee4e 100644 --- a/spring-cloud-starter-gateway-mvc/pom.xml +++ b/spring-cloud-starter-gateway-mvc/pom.xml @@ -34,5 +34,10 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-properties-migrator + diff --git a/spring-cloud-starter-gateway-server-webflux/pom.xml b/spring-cloud-starter-gateway-server-webflux/pom.xml index ab94fcc5..ed3b79c4 100644 --- a/spring-cloud-starter-gateway-server-webflux/pom.xml +++ b/spring-cloud-starter-gateway-server-webflux/pom.xml @@ -33,5 +33,10 @@ org.springframework.boot spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-properties-migrator + diff --git a/spring-cloud-starter-gateway-server-webmvc/pom.xml b/spring-cloud-starter-gateway-server-webmvc/pom.xml index 00420392..14b339e1 100644 --- a/spring-cloud-starter-gateway-server-webmvc/pom.xml +++ b/spring-cloud-starter-gateway-server-webmvc/pom.xml @@ -33,5 +33,10 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-properties-migrator + diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 8de3f70e..9705acd7 100644 --- a/spring-cloud-starter-gateway/pom.xml +++ b/spring-cloud-starter-gateway/pom.xml @@ -34,5 +34,10 @@ org.springframework.boot spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-properties-migrator + From ec60c2e2a81d03c31aa67719347afa754080c191 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Tue, 20 May 2025 14:30:34 -0400 Subject: [PATCH 09/15] formatting --- ...atewayServerMvcAutoConfigurationTests.java | 22 +++++++++---------- ...ServerMvcLoadBalancerIntegrationTests.java | 8 +++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java index 71e3e638..01f8f9f4 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/GatewayServerMvcAutoConfigurationTests.java @@ -209,22 +209,22 @@ public class GatewayServerMvcAutoConfigurationTests { @Test void loadBalancerFunctionHandlerAdded() { new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, - HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, - HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, - RestClientAutoConfiguration.class)) - .run(context -> assertThat(context).hasBean("lbHandlerFunctionDefinition")); + .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, + HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, + HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, + RestClientAutoConfiguration.class)) + .run(context -> assertThat(context).hasBean("lbHandlerFunctionDefinition")); } @Test void loadBalancerFunctionHandlerNotAddedWhenNoLoadBalancerClientOnClasspath() { new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, - HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, - HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, - RestClientAutoConfiguration.class)) - .withClassLoader(new FilteredClassLoader(LoadBalancerClient.class)) - .run(context -> assertThat(context).doesNotHaveBean("lbHandlerFunctionDefinition")); + .withConfiguration(AutoConfigurations.of(FilterAutoConfiguration.class, PredicateAutoConfiguration.class, + HandlerFunctionAutoConfiguration.class, GatewayServerMvcAutoConfiguration.class, + HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, + RestClientAutoConfiguration.class)) + .withClassLoader(new FilteredClassLoader(LoadBalancerClient.class)) + .run(context -> assertThat(context).doesNotHaveBean("lbHandlerFunctionDefinition")); } @SpringBootConfiguration diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java index f0b91066..d2e5889b 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcLoadBalancerIntegrationTests.java @@ -36,7 +36,7 @@ import org.springframework.test.context.ContextConfiguration; * @author Olga Maciaszek-Sharma * */ -@SpringBootTest(classes = {ServerMvcLoadBalancerIntegrationTests.Config.class, FilterAutoConfiguration.class}, +@SpringBootTest(classes = { ServerMvcLoadBalancerIntegrationTests.Config.class, FilterAutoConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(initializers = HttpbinTestcontainers.class) @ActiveProfiles("lb") @@ -50,13 +50,13 @@ public class ServerMvcLoadBalancerIntegrationTests { @Test void shouldUseLbHandlerFunctionDefinitionToResolveHost() { - testRestClient.get() - .uri("http://localhost:" + port + "/test") - .exchange().expectStatus().isOk(); + testRestClient.get().uri("http://localhost:" + port + "/test").exchange().expectStatus().isOk(); } @SpringBootApplication @LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class) static class Config { + } + } From 4fdf22e997153960cac3039e591033f1b76cb64d Mon Sep 17 00:00:00 2001 From: Stepan Mikhailiuk Date: Thu, 22 May 2025 12:38:10 +0800 Subject: [PATCH 10/15] fix(*): fix disable builtin filter Signed-off-by: Stepan Mikhailiuk --- .../gateway/config/conditional/DisableBuiltInFiltersTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/conditional/DisableBuiltInFiltersTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/conditional/DisableBuiltInFiltersTests.java index b581dfa0..66eacd76 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/conditional/DisableBuiltInFiltersTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/conditional/DisableBuiltInFiltersTests.java @@ -100,6 +100,7 @@ public class DisableBuiltInFiltersTests { "spring.cloud.gateway.server.webflux.filter.secure-headers.enabled=false", "spring.cloud.gateway.server.webflux.filter.set-request-header.enabled=false", "spring.cloud.gateway.server.webflux.filter.set-request-host-header.enabled=false", + "spring.cloud.gateway.server.webflux.filter.set-request-uri.enabled=false", "spring.cloud.gateway.server.webflux.filter.set-response-header.enabled=false", "spring.cloud.gateway.server.webflux.filter.rewrite-response-header.enabled=false", "spring.cloud.gateway.server.webflux.filter.rewrite-location-response-header.enabled=false", From 03eb741d68849067facd45dbc312ae80fe9b2832 Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 22 May 2025 15:30:30 -0400 Subject: [PATCH 11/15] Fixing tests after merge --- .../gateway/server/mvc/filter/BeforeFilterFunctions.java | 2 +- .../server/mvc/filter/BeforeFilterFunctionsTests.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java index 578d7c7c..ce2b2404 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctions.java @@ -350,7 +350,7 @@ public abstract class BeforeFilterFunctions { queryParams.add(name, replacement); } - MultiValueMap encodedQueryParams = UriUtils.encodeQueryParams(queryParams); + MultiValueMap encodedQueryParams = MvcUtils.encodeQueryParams(queryParams); URI rewrittenUri = UriComponentsBuilder.fromUri(request.uri()) .replaceQueryParams(unmodifiableMultiValueMap(encodedQueryParams)) .build(true) diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java index f6648063..db5a4b7a 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/filter/BeforeFilterFunctionsTests.java @@ -117,9 +117,9 @@ class BeforeFilterFunctionsTests { @Test void rewriteEncodedRequestParameter() { MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/path") - .param("foo", "bar") - .param("baz[]", "qux[]") - .param("quux", "corge+") + .param("foo[]", "bar") + .param("baz", "qux") + .param("quux", "corge+") .buildRequest(null); ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList()); @@ -128,7 +128,8 @@ class BeforeFilterFunctionsTests { assertThat(result.param("foo[]")).isPresent().hasValue("replacement[]"); assertThat(result.param("quux")).isPresent().hasValue("corge+"); - assertThat(result.uri().toString()).hasToString("http://localhost/path?baz=qux&foo%5B%5D=replacement%5B%5D&quux=corge%2B"); + assertThat(result.uri().toString()) + .hasToString("http://localhost/path?quux=corge%2B&baz=qux&foo%5B%5D=replacement%5B%5D"); } @Test From 0b03ee1d26ead45a9ad1a697bbdefb4c0ce9bbce Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Thu, 22 May 2025 15:58:45 -0400 Subject: [PATCH 12/15] Update maven.yml Changes java distribution to liberica Signed-off-by: Spencer Gibb --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index be248adf..801097a0 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,7 +19,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - distribution: 'temurin' + distribution: 'liberica' java-version: '17' cache: 'maven' - name: Build with Maven From 6690c79a2dfa95f93f875a88b2c0326b369642a9 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 22 May 2025 16:22:29 -0400 Subject: [PATCH 13/15] Migrate server-webmvc properties to new namespace See gh-3647 --- .../spring-cloud-gateway-server-webmvc/starter.adoc | 2 +- .../GatewayMvcClassPathWarningAutoConfiguration.java | 3 ++- .../server/mvc/GatewayServerMvcAutoConfiguration.java | 2 +- .../gateway/server/mvc/VanillaRouterFunctionTests.java | 2 +- .../application-functionhandlerconfigtests.yml | 2 +- ...lication-propertiesbeandefinitionregistrartests.yml | 2 +- .../resources/application-streamhandlerconfigtests.yml | 2 +- .../resources/application-stripprefixstaticport.yml | 2 +- ...lication-weightrequestpredicateintegrationtests.yml | 2 +- .../additional-spring-configuration-metadata.json | 10 ---------- 10 files changed, 10 insertions(+), 19 deletions(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/starter.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/starter.adoc index 6d3b7bd8..d8f759ce 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/starter.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-webmvc/starter.adoc @@ -5,7 +5,7 @@ To include Spring Cloud Gateway Server Web MVC in your project, use the starter with a group ID of `org.springframework.cloud` and an artifact ID of `spring-cloud-starter-gateway-server-webmvc`. See the https://projects.spring.io/spring-cloud/[Spring Cloud Project page] for details on setting up your build system with the current Spring Cloud Release Train. -If you include the starter, but you do not want the gateway to be enabled, set `spring.cloud.gateway.mvc.enabled=false`. +If you include the starter, but you do not want the gateway to be enabled, set `spring.cloud.gateway.server.webmvc.enabled=false`. IMPORTANT: Spring Cloud Gateway Server MVC is built on https://spring.io/projects/spring-boot#learn[Spring Boot] and https://docs.spring.io/spring-framework/reference/web/webmvc-functional.html[Spring WebMvc.fn]. As a consequence, many of the asynchronous or reactive libraries may not apply when you use Spring Cloud Gateway Server MVC. diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayMvcClassPathWarningAutoConfiguration.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayMvcClassPathWarningAutoConfiguration.java index 4fef7bc7..21173cf9 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayMvcClassPathWarningAutoConfiguration.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/GatewayMvcClassPathWarningAutoConfiguration.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.gateway.server.mvc.config.GatewayMvcProperties; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) @AutoConfigureBefore(GatewayServerMvcAutoConfiguration.class) -@ConditionalOnProperty(name = "spring.cloud.gateway.mvc.enabled", matchIfMissing = true) +@ConditionalOnProperty(name = GatewayMvcProperties.PREFIX + ".enabled", matchIfMissing = true) public class GatewayMvcClassPathWarningAutoConfiguration { private static final Log log = LogFactory.getLog(GatewayMvcClassPathWarningAutoConfiguration.class); 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 37cd5245..2aecabe1 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 @@ -78,7 +78,7 @@ import org.springframework.web.client.RestClient; @AutoConfiguration(after = { HttpClientAutoConfiguration.class, RestTemplateAutoConfiguration.class, RestClientAutoConfiguration.class, FilterAutoConfiguration.class, HandlerFunctionAutoConfiguration.class, PredicateAutoConfiguration.class }) -@ConditionalOnProperty(name = "spring.cloud.gateway.mvc.enabled", matchIfMissing = true) +@ConditionalOnProperty(name = GatewayMvcProperties.PREFIX + ".enabled", matchIfMissing = true) @Import(GatewayMvcPropertiesBeanDefinitionRegistrar.class) @ImportRuntimeHints(GatewayMvcAotRuntimeHintsRegistrar.class) public class GatewayServerMvcAutoConfiguration { 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 fd96c938..81d1128c 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,7 +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.cloud.gateway.mvc.http-client.type=jdk" }, +@SpringBootTest(properties = { "spring.http.client.factory=jdk" }, webEnvironment = WebEnvironment.RANDOM_PORT) @ContextConfiguration(initializers = HttpbinTestcontainers.class) public class VanillaRouterFunctionTests { diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-functionhandlerconfigtests.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-functionhandlerconfigtests.yml index c7430ca4..847e7057 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application-functionhandlerconfigtests.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-functionhandlerconfigtests.yml @@ -1,4 +1,4 @@ -spring.cloud.gateway.mvc: +spring.cloud.gateway.server.webmvc: routesMap: testsimplefunction: uri: fn:upper diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-propertiesbeandefinitionregistrartests.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-propertiesbeandefinitionregistrartests.yml index a91fe14d..cd55ac63 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application-propertiesbeandefinitionregistrartests.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-propertiesbeandefinitionregistrartests.yml @@ -1,4 +1,4 @@ -spring.cloud.gateway.mvc: +spring.cloud.gateway.server.webmvc: routesMap: route1: uri: https://example1.com diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-streamhandlerconfigtests.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-streamhandlerconfigtests.yml index 3e97fc80..00cfc6b9 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application-streamhandlerconfigtests.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-streamhandlerconfigtests.yml @@ -1,4 +1,4 @@ -spring.cloud.gateway.mvc: +spring.cloud.gateway.server.webmvc: routesMap: testsimplestream: uri: stream:hello-out-0 diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml index c27795c3..184cfee5 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-stripprefixstaticport.yml @@ -1,5 +1,5 @@ strip.prefix.static.uri: http://${httpbin.host}:${httpbin.port} -spring.cloud.gateway.mvc: +spring.cloud.gateway.server.webmvc: routes: - id: strip_prefix_static_port_config uri: ${strip.prefix.static.uri} diff --git a/spring-cloud-gateway-server-mvc/src/test/resources/application-weightrequestpredicateintegrationtests.yml b/spring-cloud-gateway-server-mvc/src/test/resources/application-weightrequestpredicateintegrationtests.yml index 69d927b8..f4dc97ad 100644 --- a/spring-cloud-gateway-server-mvc/src/test/resources/application-weightrequestpredicateintegrationtests.yml +++ b/spring-cloud-gateway-server-mvc/src/test/resources/application-weightrequestpredicateintegrationtests.yml @@ -1,4 +1,4 @@ -spring.cloud.gateway.mvc: +spring.cloud.gateway.server.webmvc: routes: - id: weight_high_test uri: https://examplel1.com 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 1a646d71..13464a13 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 @@ -1966,16 +1966,6 @@ "since": "4.3.0" } }, - { - "name": "spring.cloud.gateway.mvc.routes", - "type": "java.util.List", - "description": "List of Routes.", - "deprecated": true, - "deprecation": { - "replacement": "spring.cloud.gateway.server.webflux.mvc.routes", - "since": "4.3.0" - } - }, { "name": "spring.cloud.gateway.observability.enabled", "type": "java.lang.Boolean", From fb2a32bb81df0d28b906365d2ab620757bb7113b Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 22 May 2025 16:30:04 -0400 Subject: [PATCH 14/15] Attempt to get tests to pass in github actions --- spring-cloud-gateway-server-mvc/pom.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index ad20bf03..2e16c44c 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -146,4 +146,19 @@ test + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + host + + + + + From 5177890943e734bdf9a3f5d9f788ad3a6e629688 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Thu, 22 May 2025 18:25:47 -0400 Subject: [PATCH 15/15] Moves github action system property to a profile --- spring-cloud-gateway-server-mvc/pom.xml | 39 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index 2e16c44c..01c47d60 100644 --- a/spring-cloud-gateway-server-mvc/pom.xml +++ b/spring-cloud-gateway-server-mvc/pom.xml @@ -147,18 +147,29 @@ - - - - org.apache.maven.plugins - maven-surefire-plugin - - - - host - - - - - + + + github_actions + + + + env.GITHUB_ACTIONS + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + host + + + + + + +