From 350c9cda6dcce96f76f41b91e64bf8884c6d440e Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Thu, 6 Mar 2025 21:26:50 +0800 Subject: [PATCH 01/17] RetryGatewayFilterFactory RetryConfig support Jitter & Timeout Signed-off-by: jiangyuan --- .../factory/RetryGatewayFilterFactory.java | 76 ++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index d8046e27..ad6889e5 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -30,6 +30,7 @@ import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; import reactor.netty.Connection; import reactor.retry.Backoff; +import reactor.retry.Jitter; import reactor.retry.Repeat; import reactor.retry.RepeatContext; import reactor.retry.Retry; @@ -70,7 +71,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory shortcutFieldOrder() { return Arrays.asList("retries", "statuses", "methods", "backoff.firstBackoff", "backoff.maxBackoff", - "backoff.factor", "backoff.basedOnPreviousValue"); + "backoff.factor", "backoff.basedOnPreviousValue", "jitter.randomFactor", "timeout"); } @Override @@ -124,9 +125,16 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory exceptionRetry = null; if (!retryConfig.getExceptions().isEmpty()) { @@ -163,6 +171,14 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory= 0"); + } + } + + public Duration getTimeout() { + return timeout; + } + + public RetryConfig setTimeout(Duration timeout) { + this.timeout = timeout; + return this; + } + + public JitterConfig getJitter() { + return jitter; + } + + public RetryConfig setJitter(JitterConfig jitter) { + this.jitter = jitter; + return this; } public BackoffConfig getBackoff() { @@ -439,4 +487,28 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory= 0 && randomFactor <= 1, "random factor must be between 0 and 1 (default 0.5)"); + } + + public JitterConfig() { + } + + public JitterConfig(double randomFactor) { + this.randomFactor = randomFactor; + } + + public double getRandomFactor() { + return randomFactor; + } + + public void setRandomFactor(double randomFactor) { + this.randomFactor = randomFactor; + } + } + } From 9eb9165927d1d12af1a61b3d3675502448b68572 Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Wed, 12 Mar 2025 15:44:15 +0800 Subject: [PATCH 02/17] add docs and unit-test Signed-off-by: jiangyuan --- .../retry-factory.adoc | 13 ++++++++++++- .../factory/RetryGatewayFilterFactory.java | 4 +++- ...yGatewayFilterFactoryIntegrationTests.java | 12 ++++++++++++ .../test/resources/application-retrytests.yml | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway/gatewayfilter-factories/retry-factory.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway/gatewayfilter-factories/retry-factory.adoc index 62d58904..afc650f5 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway/gatewayfilter-factories/retry-factory.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway/gatewayfilter-factories/retry-factory.adoc @@ -12,6 +12,9 @@ The `Retry` `GatewayFilter` factory supports the following parameters: Retries are performed after a backoff interval of `firstBackoff * (factor ^ n)`, where `n` is the iteration. If `maxBackoff` is configured, the maximum backoff applied is limited to `maxBackoff`. If `basedOnPreviousValue` is true, the backoff is calculated by using `prevBackoff * factor`. +* `jitter`: The configured random jitter for the retries. +Generating a backoff between `[backoff - backoff*randomFactor, backoff + backoff*randomFactor]` +* `timeout`: The configured timeout for the retries. The following defaults are configured for `Retry` filter, if enabled: @@ -20,6 +23,8 @@ The following defaults are configured for `Retry` filter, if enabled: * `methods`: GET method * `exceptions`: `IOException` and `TimeoutException` * `backoff`: disabled +* `jitter`: disabled +* `timeout`: unlimited The following listing configures a Retry `GatewayFilter`: @@ -45,6 +50,9 @@ spring: maxBackoff: 50ms factor: 2 basedOnPreviousValue: false + jitter: + randomFactor: 0.5 + timeout: 100ms ---- NOTE: When using the retry filter with a `forward:` prefixed URL, the target endpoint should be written carefully so that, in case of an error, it does not do anything that could result in a response being sent to the client and committed. @@ -77,10 +85,13 @@ spring: maxBackoff: 50ms factor: 2 basedOnPreviousValue: false + jitter: + randomFactor: 0.5 + timeout: 100ms - id: retryshortcut_route uri: https://example.org filters: - - Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false + - Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false,0.5,100ms ---- diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index ad6889e5..91a73ae0 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -492,7 +492,8 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory= 0 && randomFactor <= 1, "random factor must be between 0 and 1 (default 0.5)"); + Assert.isTrue(randomFactor >= 0 && randomFactor <= 1, + "random factor must be between 0 and 1 (default 0.5)"); } public JitterConfig() { @@ -509,6 +510,7 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory Date: Thu, 13 Mar 2025 12:31:46 +0800 Subject: [PATCH 03/17] add unit-test Signed-off-by: jiangyuan --- .../factory/RetryGatewayFilterFactory.java | 9 ++++++-- ...yGatewayFilterFactoryIntegrationTests.java | 21 +++++++++++++++++++ .../test/resources/application-retrytests.yml | 19 ----------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index 91a73ae0..1f42e412 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -173,11 +173,11 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory timeout + testClient.get() + .uri("/retry?key=retry-with-backoff-timeout&count=3") + .header(HttpHeaders.HOST, "www.retrywithbackofftimeout.org") + .exchange() + .expectStatus() + .isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + } + @Test public void retryFilterGetJavaDsl() { testClient.get() @@ -375,6 +386,16 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest r -> r.host("**.retrywithbackoff.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { config.setRetries(2).setBackoff(Duration.ofMillis(100), null, 2, true); })).uri(uri)) + .route("retry_with_backoff_jitter_timeout_test", + r -> r.host("**.retrywithbackoffjittertimeout.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { + config.setRetries(3).setBackoff(Duration.ofMillis(50), Duration.ofMillis(100), 2, true) + .setJitter(0.1).setTimeout(Duration.ofMillis(1000)); + })).uri(uri)) + .route("retry_with_backoff_timeout_test", + r -> r.host("**.retrywithbackofftimeout.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { + config.setRetries(3).setBackoff(Duration.ofMillis(100), null, 2, true) + .setTimeout(Duration.ofMillis(100)); + })).uri(uri)) .route("retry_with_loadbalancer", r -> r.host("**.retrywithloadbalancer.org") diff --git a/spring-cloud-gateway-server/src/test/resources/application-retrytests.yml b/spring-cloud-gateway-server/src/test/resources/application-retrytests.yml index c9f8cc8c..ea5e1be8 100644 --- a/spring-cloud-gateway-server/src/test/resources/application-retrytests.yml +++ b/spring-cloud-gateway-server/src/test/resources/application-retrytests.yml @@ -29,22 +29,3 @@ spring: - name: Retry args: methods: GET,POST - # ===================================== - - id: retry_with_backoff_jitter_timeout_test - uri: ${test.uri} - predicates: - - Host=**.retrywithbackoffjittertimeout.org - filters: - - name: Retry - args: - retries: 3 - statuses: INTERNAL_SERVER_ERROR - methods: GET - backoff: - firstBackoff: 10ms - maxBackoff: 50ms - factor: 2 - basedOnPreviousValue: false - jitter: - randomFactor: 0.5 - timeout: 200ms \ No newline at end of file From 5e9753efb6a5400ec69ffa85e899799331ef3a06 Mon Sep 17 00:00:00 2001 From: joecqupt Date: Sat, 15 Mar 2025 13:47:18 +0800 Subject: [PATCH 04/17] add toString info Signed-off-by: joecqupt --- .../factory/RetryGatewayFilterFactory.java | 20 ++++++++++- ...yGatewayFilterFactoryIntegrationTests.java | 35 +++++++++++-------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index 1f42e412..e47307da 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -42,6 +42,7 @@ import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.support.HasRouteId; import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.cloud.gateway.support.TimeoutException; +import org.springframework.core.style.ToStringCreator; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus.Series; @@ -135,7 +136,6 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory exceptionRetry = null; if (!retryConfig.getExceptions().isEmpty()) { Predicate> retryContextPredicate = context -> { @@ -196,6 +196,9 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory timeout testClient.get() - .uri("/retry?key=retry-with-backoff-timeout&count=3") - .header(HttpHeaders.HOST, "www.retrywithbackofftimeout.org") - .exchange() - .expectStatus() - .isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + .uri("/retry?key=retry-with-backoff-timeout&count=3") + .header(HttpHeaders.HOST, "www.retrywithbackofftimeout.org") + .exchange() + .expectStatus() + .isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); } @Test @@ -386,16 +386,21 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest r -> r.host("**.retrywithbackoff.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { config.setRetries(2).setBackoff(Duration.ofMillis(100), null, 2, true); })).uri(uri)) - .route("retry_with_backoff_jitter_timeout_test", - r -> r.host("**.retrywithbackoffjittertimeout.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { - config.setRetries(3).setBackoff(Duration.ofMillis(50), Duration.ofMillis(100), 2, true) - .setJitter(0.1).setTimeout(Duration.ofMillis(1000)); - })).uri(uri)) - .route("retry_with_backoff_timeout_test", - r -> r.host("**.retrywithbackofftimeout.org").filters(f -> f.prefixPath("/httpbin").retry(config -> { - config.setRetries(3).setBackoff(Duration.ofMillis(100), null, 2, true) - .setTimeout(Duration.ofMillis(100)); - })).uri(uri)) + .route("retry_with_backoff_jitter_timeout_test", r -> r.host("**.retrywithbackoffjittertimeout.org") + .filters(f -> f.prefixPath("/httpbin").retry(config -> { + config.setRetries(3) + .setBackoff(Duration.ofMillis(50), Duration.ofMillis(100), 2, true) + .setJitter(0.1) + .setTimeout(Duration.ofMillis(1000)); + })) + .uri(uri)) + .route("retry_with_backoff_timeout_test", r -> r.host("**.retrywithbackofftimeout.org") + .filters(f -> f.prefixPath("/httpbin").retry(config -> { + config.setRetries(3) + .setBackoff(Duration.ofMillis(100), null, 2, true) + .setTimeout(Duration.ofMillis(100)); + })) + .uri(uri)) .route("retry_with_loadbalancer", r -> r.host("**.retrywithloadbalancer.org") From f6e68fac8ecf5ce645eafa108aaf0a0e2e9126fb Mon Sep 17 00:00:00 2001 From: Jonathon Henderson Date: Sat, 29 Jun 2024 18:32:26 +0100 Subject: [PATCH 05/17] Adds support for saving original request URL to request attributes This enables X-Forwarded-Prefix. Fixes gh-3354 Fixes gh-3443 --- .../gateway/server/mvc/common/MvcUtils.java | 15 +++++++++++++ .../mvc/filter/BeforeFilterFunctions.java | 3 +++ .../XForwardedRequestHeadersFilter.java | 10 ++++----- .../server/mvc/ServerMvcIntegrationTests.java | 20 ++++++++++++++++-- .../server/mvc/test/HttpbinUriResolver.java | 21 +++++++++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 72f30289..5eec2dd6 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -72,6 +73,11 @@ public abstract class MvcUtils { */ public static final String GATEWAY_ATTRIBUTES_ATTR = qualify("gatewayAttributes"); + /** + * Gateway original request URL attribute name. + */ + public static final String GATEWAY_ORIGINAL_REQUEST_URL_ATTR = qualify("gatewayOriginalRequestUrl"); + /** * Gateway request URL attribute name. */ @@ -250,6 +256,15 @@ public abstract class MvcUtils { request.servletRequest().setAttribute(GATEWAY_REQUEST_URL_ATTR, url); } + public static void addOriginalRequestUrl(ServerRequest request, URI url) { + LinkedHashSet urls = getAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR); + if (urls == null) { + urls = new LinkedHashSet<>(); + } + urls.add(url); + putAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR, urls); + } + private record ByteArrayInputMessage(ServerRequest request, ByteArrayInputStream body) implements HttpInputMessage { @Override 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 650f9ca6..352bacbb 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 @@ -389,6 +389,7 @@ public abstract class BeforeFilterFunctions { public static Function stripPrefix(int parts) { return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); // TODO: gateway url attributes String path = request.uri().getRawPath(); // TODO: begin duplicate code from StripPrefixGatewayFilterFactory @@ -414,6 +415,8 @@ public abstract class BeforeFilterFunctions { .replacePath(newPath.toString()) .build(true) .toUri(); + MvcUtils.setRequestUrl(request, prefixedUri); + return ServerRequest.from(request).uri(prefixedUri).build(); }; } 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 db5e0539..9b8b9bcb 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 @@ -25,6 +25,7 @@ import java.util.Map; 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.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.util.ObjectUtils; @@ -397,18 +398,15 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request // - see XForwardedHeadersFilterTests, so first get uris, then extract paths // and remove one from another if it's the ending part. - LinkedHashSet originalUris = null; // TODO: - // exchange.getAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR); - URI requestUri = null; // TODO: - // exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); + LinkedHashSet originalUris = MvcUtils.getAttribute(request, + MvcUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR); + URI requestUri = MvcUtils.getAttribute(request, MvcUtils.GATEWAY_REQUEST_URL_ATTR); if (originalUris != null && requestUri != null) { originalUris.forEach(originalUri -> { if (originalUri != null && originalUri.getPath() != null) { - String prefix = originalUri.getPath(); - // strip trailing slashes before checking if request path is end // of original path String originalUriPath = stripTrailingSlash(originalUri); 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 9deff0ed..d5f46144 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 @@ -242,6 +242,14 @@ public class ServerMvcIntegrationTests { .consumeWith(res -> { Map map = res.getResponseBody(); Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefix"); }); } @@ -260,6 +268,14 @@ public class ServerMvcIntegrationTests { Map map = res.getResponseBody(); assertThat(map).containsEntry("data", "hello"); Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefixPost"); }); } @@ -1068,9 +1084,9 @@ public class ServerMvcIntegrationTests { public RouterFunction gatewayRouterFunctionsStripPrefix() { // @formatter:off return route(GET("/long/path/to/get"), http()) - .filter(new HttpbinUriResolver()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefix")) + .filter(new HttpbinUriResolver(true)) .withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "teststripprefix"); // @formatter:on } @@ -1080,9 +1096,9 @@ public class ServerMvcIntegrationTests { // @formatter:off return route("teststripprefixpost") .route(POST("/long/path/to/post").and(host("**.stripprefixpost.org")), http()) - .filter(new HttpbinUriResolver()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefixPost")) + .filter(new HttpbinUriResolver(true)) .build(); // @formatter:on } diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java index c46e1f25..0d327185 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java @@ -17,6 +17,7 @@ package org.springframework.cloud.gateway.server.mvc.test; import java.net.URI; +import java.net.URISyntaxException; import java.util.function.Function; import org.springframework.cloud.gateway.server.mvc.common.MvcUtils; @@ -30,12 +31,32 @@ import org.springframework.web.servlet.function.ServerResponse; public class HttpbinUriResolver implements Function, HandlerFilterFunction { + private final boolean preservePath; + + public HttpbinUriResolver(boolean preservePath) { + this.preservePath = preservePath; + } + + public HttpbinUriResolver() { + this(false); + } + protected URI uri(ServerRequest request) { ApplicationContext context = MvcUtils.getApplicationContext(request); Integer port = context.getEnvironment().getProperty("httpbin.port", Integer.class); String host = context.getEnvironment().getProperty("httpbin.host"); Assert.hasText(host, "httpbin.host is not set, did you initialize HttpbinTestcontainers?"); Assert.notNull(port, "httpbin.port is not set, did you initialize HttpbinTestcontainers?"); + if (preservePath) { + URI original = request.uri(); + try { + return new URI("http", original.getUserInfo(), host, port, original.getPath(), + original.getQuery(), original.getFragment()); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + return URI.create(String.format("http://%s:%d", host, port)); } From 9843fdf1478ca7c310d7ca5e8221336d3aecaacc Mon Sep 17 00:00:00 2001 From: spencergibb Date: Mon, 17 Mar 2025 15:44:11 -0400 Subject: [PATCH 06/17] Updates for forwarded prefix header. Adjusts all path related filters to add the original uri and set the request url See gh-3443 --- .../gateway/server/mvc/common/MvcUtils.java | 8 +-- .../mvc/filter/BeforeFilterFunctions.java | 16 ++--- .../filter/LoadBalancerFilterFunctions.java | 2 + .../server/mvc/ServerMvcIntegrationTests.java | 63 ++++++++++++++----- .../server/mvc/test/HttpbinUriResolver.java | 27 +++----- 5 files changed, 70 insertions(+), 46 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 5eec2dd6..05c073ed 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -256,13 +256,11 @@ public abstract class MvcUtils { request.servletRequest().setAttribute(GATEWAY_REQUEST_URL_ATTR, url); } + @SuppressWarnings("unchecked") public static void addOriginalRequestUrl(ServerRequest request, URI url) { - LinkedHashSet urls = getAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR); - if (urls == null) { - urls = new LinkedHashSet<>(); - } + LinkedHashSet urls = (LinkedHashSet) request.attributes() + .computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR, s -> new LinkedHashSet<>()); urls.add(url); - putAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR, urls); } private record ByteArrayInputMessage(ServerRequest request, ByteArrayInputStream body) implements HttpInputMessage { 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 352bacbb..96dac3d1 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 @@ -189,12 +189,14 @@ public abstract class BeforeFilterFunctions { final UriTemplate uriTemplate = new UriTemplate(prefix); return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); Map uriVariables = MvcUtils.getUriTemplateVariables(request); URI uri = uriTemplate.expand(uriVariables); String newPath = uri.getRawPath() + request.uri().getRawPath(); URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(newPath).build().toUri(); + MvcUtils.setRequestUrl(request, prefixedUri); return ServerRequest.from(request).uri(prefixedUri).build(); }; } @@ -326,7 +328,7 @@ public abstract class BeforeFilterFunctions { String normalizedReplacement = replacement.replace("$\\", "$"); Pattern pattern = Pattern.compile(regexp); return request -> { - // TODO: original request url + MvcUtils.addOriginalRequestUrl(request, request.uri()); String path = request.uri().getRawPath(); String newPath = pattern.matcher(path).replaceAll(normalizedReplacement); @@ -334,8 +336,7 @@ public abstract class BeforeFilterFunctions { ServerRequest modified = ServerRequest.from(request).uri(rewrittenUri).build(); - // TODO: can this be restored at some point? - // MvcUtils.setRequestUrl(modified, modified.uri()); + MvcUtils.setRequestUrl(request, rewrittenUri); return modified; }; } @@ -351,14 +352,13 @@ public abstract class BeforeFilterFunctions { UriTemplate uriTemplate = new UriTemplate(path); return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); Map uriVariables = MvcUtils.getUriTemplateVariables(request); URI uri = uriTemplate.expand(uriVariables); - URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()) - .replacePath(uri.getRawPath()) - .build(true) - .toUri(); - return ServerRequest.from(request).uri(prefixedUri).build(); + URI newUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(uri.getRawPath()).build(true).toUri(); + MvcUtils.setRequestUrl(request, newUri); + return ServerRequest.from(request).uri(newUri).build(); }; } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java index ab6d47dc..db7b1464 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java @@ -63,6 +63,8 @@ public abstract class LoadBalancerFilterFunctions { public static HandlerFilterFunction lb(String serviceId, BiFunction reconstructUriFunction) { return (request, next) -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); + LoadBalancerClientFactory clientFactory = getApplicationContext(request) .getBean(LoadBalancerClientFactory.class); Set supportedLifecycleProcessors = LoadBalancerLifecycleValidator 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 d5f46144..4188d73a 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 @@ -235,6 +235,7 @@ public class ServerMvcIntegrationTests { public void stripPrefixWorks() { restClient.get() .uri("/long/path/to/get") + .header("Host", "www.stripprefix.org") .exchange() .expectStatus() .isOk() @@ -242,14 +243,13 @@ public class ServerMvcIntegrationTests { .consumeWith(res -> { Map map = res.getResponseBody(); Map headers = getMap(map, "headers"); - assertThat(headers).containsKeys( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); - assertThat(headers).containsEntry( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefix"); }); } @@ -268,18 +268,40 @@ public class ServerMvcIntegrationTests { Map map = res.getResponseBody(); assertThat(map).containsEntry("data", "hello"); Map headers = getMap(map, "headers"); - assertThat(headers).containsKeys( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); - assertThat(headers).containsEntry( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefixPost"); }); } + @Test + public void stripPrefixLbWorks() { + restClient.get() + .uri("/long/path/to/get") + .header("Host", "www.stripprefixlb.org") + .exchange() + .expectStatus() + .isOk() + .expectBody(Map.class) + .consumeWith(res -> { + Map map = res.getResponseBody(); + Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); + assertThat(headers).containsEntry("X-Test", "stripPrefix"); + }); + } + @Test public void setStatusGatewayRouterFunctionWorks() { restClient.get() @@ -1074,8 +1096,8 @@ public class ServerMvcIntegrationTests { // @formatter:off return route("testsetpath") .route(POST("/mycustompath{extra}").and(host("**.setpathpost.org")), http()) - .filter(new HttpbinUriResolver()) .filter(setPath("/{extra}")) + .filter(new HttpbinUriResolver()) .build(); // @formatter:on } @@ -1083,11 +1105,12 @@ public class ServerMvcIntegrationTests { @Bean public RouterFunction gatewayRouterFunctionsStripPrefix() { // @formatter:off - return route(GET("/long/path/to/get"), http()) + return route("teststripprefix") + .route(GET("/long/path/to/get").and(host("**.stripprefix.org")), http()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefix")) - .filter(new HttpbinUriResolver(true)) - .withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "teststripprefix"); + .filter(new HttpbinUriResolver()) + .build(); // @formatter:on } @@ -1098,7 +1121,19 @@ public class ServerMvcIntegrationTests { .route(POST("/long/path/to/post").and(host("**.stripprefixpost.org")), http()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefixPost")) - .filter(new HttpbinUriResolver(true)) + .filter(new HttpbinUriResolver()) + .build(); + // @formatter:on + } + + @Bean + public RouterFunction gatewayRouterFunctionsStripPrefixLb() { + // @formatter:off + return route("teststripprefix") + .route(GET("/long/path/to/get").and(host("**.stripprefixlb.org")), http()) + .filter(stripPrefix(3)) + .filter(addRequestHeader("X-Test", "stripPrefix")) + .filter(lb("httpbin")) .build(); // @formatter:on } @@ -1433,8 +1468,8 @@ public class ServerMvcIntegrationTests { return route("requestheadertorequesturi") .route(cloudFoundryRouteService().and(host("**.requestheadertorequesturi.org")), http()) //.before(new HttpbinUriResolver()) NO URI RESOLVER! - .before(requestHeaderToRequestUri("X-CF-Forwarded-Url")) .filter(setPath("/hello")) + .before(requestHeaderToRequestUri("X-CF-Forwarded-Url")) .build(); // @formatter:on } diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java index 0d327185..93b6bb51 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.server.mvc.test; +import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.net.URISyntaxException; import java.util.function.Function; @@ -31,33 +32,21 @@ import org.springframework.web.servlet.function.ServerResponse; public class HttpbinUriResolver implements Function, HandlerFilterFunction { - private final boolean preservePath; - - public HttpbinUriResolver(boolean preservePath) { - this.preservePath = preservePath; - } - - public HttpbinUriResolver() { - this(false); - } - protected URI uri(ServerRequest request) { ApplicationContext context = MvcUtils.getApplicationContext(request); Integer port = context.getEnvironment().getProperty("httpbin.port", Integer.class); String host = context.getEnvironment().getProperty("httpbin.host"); Assert.hasText(host, "httpbin.host is not set, did you initialize HttpbinTestcontainers?"); Assert.notNull(port, "httpbin.port is not set, did you initialize HttpbinTestcontainers?"); - if (preservePath) { - URI original = request.uri(); - try { - return new URI("http", original.getUserInfo(), host, port, original.getPath(), - original.getQuery(), original.getFragment()); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } + URI original = request.uri(); + try { + return new URI("http", original.getUserInfo(), host, port, original.getPath(), original.getQuery(), + original.getFragment()); + } + catch (URISyntaxException e) { + throw new UndeclaredThrowableException(e); } - return URI.create(String.format("http://%s:%d", host, port)); } @Override From c1c741d0227850ac8e2cfd0f0015db788e4ddf20 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Mon, 17 Mar 2025 16:12:09 -0400 Subject: [PATCH 07/17] For lb: scheme, put associated filters last. This makes sure the lb filter runs after path modifying filters like stripPrefix. See gh-3443 --- .../filters/loadbalancer.adoc | 2 ++ .../filters/prefixpath.adoc | 3 ++- .../filters/rewritepath.adoc | 1 + .../spring-cloud-gateway-server-mvc/filters/setpath.adoc | 1 + .../filters/stripprefix.adoc | 1 + .../server/mvc/config/RouterFunctionHolderFactory.java | 9 ++++++++- ...GatewayMvcPropertiesBeanDefinitionRegistrarTests.java | 4 ++-- ...pplication-propertiesbeandefinitionregistrartests.yml | 5 ++++- 8 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc index 58859f9c..2135aaf2 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc @@ -43,6 +43,8 @@ spring: - Path=/api/** ---- +WARNING: If using the `lb()` filter, it needs to be after any filter that manipulates the path such as `setPath()` or `stripPrefix()`, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. + NOTE: By default, when a service instance cannot be found by the `ReactorLoadBalancer`, a `503` is returned. // TODO: implement use404 // You can configure the gateway to return a `404` by setting `spring.cloud.gateway.loadbalancer.use404=true`. diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc index 2313b6e5..5bc8b5e8 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc @@ -33,7 +33,7 @@ class RouteConfiguration { public RouterFunction gatewayRouterFunctionsPrefixPath() { return route("prefixpath_route") .GET("/**", http("https://example.org")) - .before("/mypath") + .before(prefixPath("/mypath")) .build(); } } @@ -42,3 +42,4 @@ class RouteConfiguration { This prefixes `/mypath` to the path of all matching requests. So a request to `/hello` is sent to `/mypath/hello`. +WARNING: If using the `lb()` filter, it needs to be after the `prefixPath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc index 7247db46..3b50b615 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc @@ -43,3 +43,4 @@ class RouteConfiguration { For a request path of `/red/blue`, this sets the path to `/blue` before making the downstream request. Note that in `application.yml` the `$` should be replaced with `$\` because of the YAML specification. +WARNING: If using the `lb()` filter, it needs to be after the `rewritePath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc index 261345e6..9355a068 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc @@ -45,3 +45,4 @@ class RouteConfiguration { For a request path of `/red/blue`, this sets the path to `/blue` before making the downstream request. +WARNING: If using the `lb()` filter, it needs to be after the `setPath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc index ee2d2efa..dc2be798 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc @@ -43,3 +43,4 @@ class RouteConfiguration { When a request is made through the gateway to `/name/blue/red`, the request made to `nameservice` looks like `https://nameservice/red`. +WARNING: If using the `lb()` filter, it needs to be after the `stripPrefix()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java index 687bdec8..dcebc7e7 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.server.mvc.config; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -178,12 +179,15 @@ public class RouterFunctionHolderFactory { NormalizedOperationMethod normalizedOpMethod = handlerOperationMethod.get(); Object response = invokeOperation(normalizedOpMethod, normalizedOpMethod.getNormalizedArgs()); HandlerFunction handlerFunction = null; + + // filters added by HandlerDiscoverer need to go last, so save them + List> handlerFilterFunctionFilters = new ArrayList<>(); if (response instanceof HandlerFunction) { handlerFunction = (HandlerFunction) response; } else if (response instanceof HandlerDiscoverer.Result result) { handlerFunction = result.getHandlerFunction(); - result.getFilters().forEach(builder::filter); + handlerFilterFunctionFilters.addAll(result.getFilters()); } if (handlerFunction == null) { throw new IllegalStateException( @@ -221,6 +225,9 @@ public class RouterFunctionHolderFactory { translate(filterOperations, filterProperties.getName(), args, HandlerFilterFunction.class, builder::filter); }); + // HandlerDiscoverer filters need higher priority, so put them last + handlerFilterFunctionFilters.forEach(builder::filter); + builder.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, routeId); return builder.build(); diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java index f4f7675c..861b1694 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java @@ -122,7 +122,7 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests { predicate.accept(new AbstractRequestPredicatesVisitor() { @Override public void path(String pattern) { - assertThat(pattern).isEqualTo("/anything/listRoute3"); + assertThat(pattern).isEqualTo("/extra/anything/listRoute3"); } @Override @@ -181,7 +181,7 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests { @SuppressWarnings("unchecked") public void lbRouteWorks() { restClient.get() - .uri("/anything/listRoute3") + .uri("/extra/anything/listRoute3") .header("MyHeaderName", "MyHeaderVal") .exchange() .expectStatus() 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 5270b8cb..a91fe14d 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 @@ -38,9 +38,12 @@ spring.cloud.gateway.mvc: - id: listRoute3 uri: lb://httpbin predicates: - - Path=/anything/listRoute3 + - Path=/extra/anything/listRoute3 - Header=MyHeaderName,MyHeader.* filters: + - name: StripPrefix + args: + parts: 1 - name: AddRequestHeader args: name: X-Test From d6d8a28e7fcc12f38d2108d86bd5c3118bd5c719 Mon Sep 17 00:00:00 2001 From: Jonathon Henderson Date: Sat, 29 Jun 2024 18:32:26 +0100 Subject: [PATCH 08/17] Adds support for saving original request URL to request attributes This enables X-Forwarded-Prefix. Fixes gh-3354 Fixes gh-3443 --- .../gateway/server/mvc/common/MvcUtils.java | 15 +++++++++++++ .../mvc/filter/BeforeFilterFunctions.java | 3 +++ .../XForwardedRequestHeadersFilter.java | 10 ++++----- .../server/mvc/ServerMvcIntegrationTests.java | 20 ++++++++++++++++-- .../server/mvc/test/HttpbinUriResolver.java | 21 +++++++++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 72f30289..5eec2dd6 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -72,6 +73,11 @@ public abstract class MvcUtils { */ public static final String GATEWAY_ATTRIBUTES_ATTR = qualify("gatewayAttributes"); + /** + * Gateway original request URL attribute name. + */ + public static final String GATEWAY_ORIGINAL_REQUEST_URL_ATTR = qualify("gatewayOriginalRequestUrl"); + /** * Gateway request URL attribute name. */ @@ -250,6 +256,15 @@ public abstract class MvcUtils { request.servletRequest().setAttribute(GATEWAY_REQUEST_URL_ATTR, url); } + public static void addOriginalRequestUrl(ServerRequest request, URI url) { + LinkedHashSet urls = getAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR); + if (urls == null) { + urls = new LinkedHashSet<>(); + } + urls.add(url); + putAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR, urls); + } + private record ByteArrayInputMessage(ServerRequest request, ByteArrayInputStream body) implements HttpInputMessage { @Override 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 650f9ca6..352bacbb 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 @@ -389,6 +389,7 @@ public abstract class BeforeFilterFunctions { public static Function stripPrefix(int parts) { return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); // TODO: gateway url attributes String path = request.uri().getRawPath(); // TODO: begin duplicate code from StripPrefixGatewayFilterFactory @@ -414,6 +415,8 @@ public abstract class BeforeFilterFunctions { .replacePath(newPath.toString()) .build(true) .toUri(); + MvcUtils.setRequestUrl(request, prefixedUri); + return ServerRequest.from(request).uri(prefixedUri).build(); }; } 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 db5e0539..9b8b9bcb 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 @@ -25,6 +25,7 @@ import java.util.Map; 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.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.util.ObjectUtils; @@ -397,18 +398,15 @@ public class XForwardedRequestHeadersFilter implements HttpHeadersFilter.Request // - see XForwardedHeadersFilterTests, so first get uris, then extract paths // and remove one from another if it's the ending part. - LinkedHashSet originalUris = null; // TODO: - // exchange.getAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR); - URI requestUri = null; // TODO: - // exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); + LinkedHashSet originalUris = MvcUtils.getAttribute(request, + MvcUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR); + URI requestUri = MvcUtils.getAttribute(request, MvcUtils.GATEWAY_REQUEST_URL_ATTR); if (originalUris != null && requestUri != null) { originalUris.forEach(originalUri -> { if (originalUri != null && originalUri.getPath() != null) { - String prefix = originalUri.getPath(); - // strip trailing slashes before checking if request path is end // of original path String originalUriPath = stripTrailingSlash(originalUri); 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 9deff0ed..d5f46144 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 @@ -242,6 +242,14 @@ public class ServerMvcIntegrationTests { .consumeWith(res -> { Map map = res.getResponseBody(); Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefix"); }); } @@ -260,6 +268,14 @@ public class ServerMvcIntegrationTests { Map map = res.getResponseBody(); assertThat(map).containsEntry("data", "hello"); Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry( + XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefixPost"); }); } @@ -1068,9 +1084,9 @@ public class ServerMvcIntegrationTests { public RouterFunction gatewayRouterFunctionsStripPrefix() { // @formatter:off return route(GET("/long/path/to/get"), http()) - .filter(new HttpbinUriResolver()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefix")) + .filter(new HttpbinUriResolver(true)) .withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "teststripprefix"); // @formatter:on } @@ -1080,9 +1096,9 @@ public class ServerMvcIntegrationTests { // @formatter:off return route("teststripprefixpost") .route(POST("/long/path/to/post").and(host("**.stripprefixpost.org")), http()) - .filter(new HttpbinUriResolver()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefixPost")) + .filter(new HttpbinUriResolver(true)) .build(); // @formatter:on } diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java index c46e1f25..0d327185 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java @@ -17,6 +17,7 @@ package org.springframework.cloud.gateway.server.mvc.test; import java.net.URI; +import java.net.URISyntaxException; import java.util.function.Function; import org.springframework.cloud.gateway.server.mvc.common.MvcUtils; @@ -30,12 +31,32 @@ import org.springframework.web.servlet.function.ServerResponse; public class HttpbinUriResolver implements Function, HandlerFilterFunction { + private final boolean preservePath; + + public HttpbinUriResolver(boolean preservePath) { + this.preservePath = preservePath; + } + + public HttpbinUriResolver() { + this(false); + } + protected URI uri(ServerRequest request) { ApplicationContext context = MvcUtils.getApplicationContext(request); Integer port = context.getEnvironment().getProperty("httpbin.port", Integer.class); String host = context.getEnvironment().getProperty("httpbin.host"); Assert.hasText(host, "httpbin.host is not set, did you initialize HttpbinTestcontainers?"); Assert.notNull(port, "httpbin.port is not set, did you initialize HttpbinTestcontainers?"); + if (preservePath) { + URI original = request.uri(); + try { + return new URI("http", original.getUserInfo(), host, port, original.getPath(), + original.getQuery(), original.getFragment()); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + return URI.create(String.format("http://%s:%d", host, port)); } From 5cc63233c60d506f29d4ddb3a9f5cab50019cb4b Mon Sep 17 00:00:00 2001 From: spencergibb Date: Mon, 17 Mar 2025 15:44:11 -0400 Subject: [PATCH 09/17] Updates for forwarded prefix header. Adjusts all path related filters to add the original uri and set the request url See gh-3443 --- .../gateway/server/mvc/common/MvcUtils.java | 8 +-- .../mvc/filter/BeforeFilterFunctions.java | 16 ++--- .../filter/LoadBalancerFilterFunctions.java | 2 + .../server/mvc/ServerMvcIntegrationTests.java | 63 ++++++++++++++----- .../server/mvc/test/HttpbinUriResolver.java | 27 +++----- 5 files changed, 70 insertions(+), 46 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 5eec2dd6..05c073ed 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -256,13 +256,11 @@ public abstract class MvcUtils { request.servletRequest().setAttribute(GATEWAY_REQUEST_URL_ATTR, url); } + @SuppressWarnings("unchecked") public static void addOriginalRequestUrl(ServerRequest request, URI url) { - LinkedHashSet urls = getAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR); - if (urls == null) { - urls = new LinkedHashSet<>(); - } + LinkedHashSet urls = (LinkedHashSet) request.attributes() + .computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR, s -> new LinkedHashSet<>()); urls.add(url); - putAttribute(request, GATEWAY_ORIGINAL_REQUEST_URL_ATTR, urls); } private record ByteArrayInputMessage(ServerRequest request, ByteArrayInputStream body) implements HttpInputMessage { 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 352bacbb..96dac3d1 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 @@ -189,12 +189,14 @@ public abstract class BeforeFilterFunctions { final UriTemplate uriTemplate = new UriTemplate(prefix); return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); Map uriVariables = MvcUtils.getUriTemplateVariables(request); URI uri = uriTemplate.expand(uriVariables); String newPath = uri.getRawPath() + request.uri().getRawPath(); URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(newPath).build().toUri(); + MvcUtils.setRequestUrl(request, prefixedUri); return ServerRequest.from(request).uri(prefixedUri).build(); }; } @@ -326,7 +328,7 @@ public abstract class BeforeFilterFunctions { String normalizedReplacement = replacement.replace("$\\", "$"); Pattern pattern = Pattern.compile(regexp); return request -> { - // TODO: original request url + MvcUtils.addOriginalRequestUrl(request, request.uri()); String path = request.uri().getRawPath(); String newPath = pattern.matcher(path).replaceAll(normalizedReplacement); @@ -334,8 +336,7 @@ public abstract class BeforeFilterFunctions { ServerRequest modified = ServerRequest.from(request).uri(rewrittenUri).build(); - // TODO: can this be restored at some point? - // MvcUtils.setRequestUrl(modified, modified.uri()); + MvcUtils.setRequestUrl(request, rewrittenUri); return modified; }; } @@ -351,14 +352,13 @@ public abstract class BeforeFilterFunctions { UriTemplate uriTemplate = new UriTemplate(path); return request -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); Map uriVariables = MvcUtils.getUriTemplateVariables(request); URI uri = uriTemplate.expand(uriVariables); - URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()) - .replacePath(uri.getRawPath()) - .build(true) - .toUri(); - return ServerRequest.from(request).uri(prefixedUri).build(); + URI newUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(uri.getRawPath()).build(true).toUri(); + MvcUtils.setRequestUrl(request, newUri); + return ServerRequest.from(request).uri(newUri).build(); }; } diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java index ab6d47dc..db7b1464 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/LoadBalancerFilterFunctions.java @@ -63,6 +63,8 @@ public abstract class LoadBalancerFilterFunctions { public static HandlerFilterFunction lb(String serviceId, BiFunction reconstructUriFunction) { return (request, next) -> { + MvcUtils.addOriginalRequestUrl(request, request.uri()); + LoadBalancerClientFactory clientFactory = getApplicationContext(request) .getBean(LoadBalancerClientFactory.class); Set supportedLifecycleProcessors = LoadBalancerLifecycleValidator 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 d5f46144..4188d73a 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 @@ -235,6 +235,7 @@ public class ServerMvcIntegrationTests { public void stripPrefixWorks() { restClient.get() .uri("/long/path/to/get") + .header("Host", "www.stripprefix.org") .exchange() .expectStatus() .isOk() @@ -242,14 +243,13 @@ public class ServerMvcIntegrationTests { .consumeWith(res -> { Map map = res.getResponseBody(); Map headers = getMap(map, "headers"); - assertThat(headers).containsKeys( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); - assertThat(headers).containsEntry( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefix"); }); } @@ -268,18 +268,40 @@ public class ServerMvcIntegrationTests { Map map = res.getResponseBody(); assertThat(map).containsEntry("data", "hello"); Map headers = getMap(map, "headers"); - assertThat(headers).containsKeys( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); - assertThat(headers).containsEntry( - XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, "/long/path/to"); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); assertThat(headers).containsEntry("X-Test", "stripPrefixPost"); }); } + @Test + public void stripPrefixLbWorks() { + restClient.get() + .uri("/long/path/to/get") + .header("Host", "www.stripprefixlb.org") + .exchange() + .expectStatus() + .isOk() + .expectBody(Map.class) + .consumeWith(res -> { + Map map = res.getResponseBody(); + Map headers = getMap(map, "headers"); + assertThat(headers).containsKeys(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER, + XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER); + assertThat(headers).containsEntry(XForwardedRequestHeadersFilter.X_FORWARDED_PREFIX_HEADER, + "/long/path/to"); + assertThat(headers).containsEntry("X-Test", "stripPrefix"); + }); + } + @Test public void setStatusGatewayRouterFunctionWorks() { restClient.get() @@ -1074,8 +1096,8 @@ public class ServerMvcIntegrationTests { // @formatter:off return route("testsetpath") .route(POST("/mycustompath{extra}").and(host("**.setpathpost.org")), http()) - .filter(new HttpbinUriResolver()) .filter(setPath("/{extra}")) + .filter(new HttpbinUriResolver()) .build(); // @formatter:on } @@ -1083,11 +1105,12 @@ public class ServerMvcIntegrationTests { @Bean public RouterFunction gatewayRouterFunctionsStripPrefix() { // @formatter:off - return route(GET("/long/path/to/get"), http()) + return route("teststripprefix") + .route(GET("/long/path/to/get").and(host("**.stripprefix.org")), http()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefix")) - .filter(new HttpbinUriResolver(true)) - .withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "teststripprefix"); + .filter(new HttpbinUriResolver()) + .build(); // @formatter:on } @@ -1098,7 +1121,19 @@ public class ServerMvcIntegrationTests { .route(POST("/long/path/to/post").and(host("**.stripprefixpost.org")), http()) .filter(stripPrefix(3)) .filter(addRequestHeader("X-Test", "stripPrefixPost")) - .filter(new HttpbinUriResolver(true)) + .filter(new HttpbinUriResolver()) + .build(); + // @formatter:on + } + + @Bean + public RouterFunction gatewayRouterFunctionsStripPrefixLb() { + // @formatter:off + return route("teststripprefix") + .route(GET("/long/path/to/get").and(host("**.stripprefixlb.org")), http()) + .filter(stripPrefix(3)) + .filter(addRequestHeader("X-Test", "stripPrefix")) + .filter(lb("httpbin")) .build(); // @formatter:on } @@ -1433,8 +1468,8 @@ public class ServerMvcIntegrationTests { return route("requestheadertorequesturi") .route(cloudFoundryRouteService().and(host("**.requestheadertorequesturi.org")), http()) //.before(new HttpbinUriResolver()) NO URI RESOLVER! - .before(requestHeaderToRequestUri("X-CF-Forwarded-Url")) .filter(setPath("/hello")) + .before(requestHeaderToRequestUri("X-CF-Forwarded-Url")) .build(); // @formatter:on } diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java index 0d327185..93b6bb51 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/test/HttpbinUriResolver.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.server.mvc.test; +import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.net.URISyntaxException; import java.util.function.Function; @@ -31,33 +32,21 @@ import org.springframework.web.servlet.function.ServerResponse; public class HttpbinUriResolver implements Function, HandlerFilterFunction { - private final boolean preservePath; - - public HttpbinUriResolver(boolean preservePath) { - this.preservePath = preservePath; - } - - public HttpbinUriResolver() { - this(false); - } - protected URI uri(ServerRequest request) { ApplicationContext context = MvcUtils.getApplicationContext(request); Integer port = context.getEnvironment().getProperty("httpbin.port", Integer.class); String host = context.getEnvironment().getProperty("httpbin.host"); Assert.hasText(host, "httpbin.host is not set, did you initialize HttpbinTestcontainers?"); Assert.notNull(port, "httpbin.port is not set, did you initialize HttpbinTestcontainers?"); - if (preservePath) { - URI original = request.uri(); - try { - return new URI("http", original.getUserInfo(), host, port, original.getPath(), - original.getQuery(), original.getFragment()); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } + URI original = request.uri(); + try { + return new URI("http", original.getUserInfo(), host, port, original.getPath(), original.getQuery(), + original.getFragment()); + } + catch (URISyntaxException e) { + throw new UndeclaredThrowableException(e); } - return URI.create(String.format("http://%s:%d", host, port)); } @Override From 5cf94a498780c97f9abc315e1afbaf3d8109b4dd Mon Sep 17 00:00:00 2001 From: spencergibb Date: Mon, 17 Mar 2025 16:12:09 -0400 Subject: [PATCH 10/17] For lb: scheme, put associated filters last. This makes sure the lb filter runs after path modifying filters like stripPrefix. See gh-3443 --- .../filters/loadbalancer.adoc | 2 ++ .../filters/prefixpath.adoc | 3 ++- .../filters/rewritepath.adoc | 1 + .../spring-cloud-gateway-server-mvc/filters/setpath.adoc | 1 + .../filters/stripprefix.adoc | 1 + .../server/mvc/config/RouterFunctionHolderFactory.java | 9 ++++++++- ...GatewayMvcPropertiesBeanDefinitionRegistrarTests.java | 4 ++-- ...pplication-propertiesbeandefinitionregistrartests.yml | 5 ++++- 8 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc index 58859f9c..2135aaf2 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/loadbalancer.adoc @@ -43,6 +43,8 @@ spring: - Path=/api/** ---- +WARNING: If using the `lb()` filter, it needs to be after any filter that manipulates the path such as `setPath()` or `stripPrefix()`, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. + NOTE: By default, when a service instance cannot be found by the `ReactorLoadBalancer`, a `503` is returned. // TODO: implement use404 // You can configure the gateway to return a `404` by setting `spring.cloud.gateway.loadbalancer.use404=true`. diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc index 2313b6e5..5bc8b5e8 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/prefixpath.adoc @@ -33,7 +33,7 @@ class RouteConfiguration { public RouterFunction gatewayRouterFunctionsPrefixPath() { return route("prefixpath_route") .GET("/**", http("https://example.org")) - .before("/mypath") + .before(prefixPath("/mypath")) .build(); } } @@ -42,3 +42,4 @@ class RouteConfiguration { This prefixes `/mypath` to the path of all matching requests. So a request to `/hello` is sent to `/mypath/hello`. +WARNING: If using the `lb()` filter, it needs to be after the `prefixPath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc index 7247db46..3b50b615 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/rewritepath.adoc @@ -43,3 +43,4 @@ class RouteConfiguration { For a request path of `/red/blue`, this sets the path to `/blue` before making the downstream request. Note that in `application.yml` the `$` should be replaced with `$\` because of the YAML specification. +WARNING: If using the `lb()` filter, it needs to be after the `rewritePath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc index 261345e6..9355a068 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/setpath.adoc @@ -45,3 +45,4 @@ class RouteConfiguration { For a request path of `/red/blue`, this sets the path to `/blue` before making the downstream request. +WARNING: If using the `lb()` filter, it needs to be after the `setPath()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc index ee2d2efa..dc2be798 100644 --- a/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/filters/stripprefix.adoc @@ -43,3 +43,4 @@ class RouteConfiguration { When a request is made through the gateway to `/name/blue/red`, the request made to `nameservice` looks like `https://nameservice/red`. +WARNING: If using the `lb()` filter, it needs to be after the `stripPrefix()` filter, otherwise the resulting url could be incorrect. The `lb:` scheme handler in configuration, automatically puts the filter in the highest precedence order. \ No newline at end of file diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java index 687bdec8..dcebc7e7 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/config/RouterFunctionHolderFactory.java @@ -16,6 +16,7 @@ package org.springframework.cloud.gateway.server.mvc.config; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -178,12 +179,15 @@ public class RouterFunctionHolderFactory { NormalizedOperationMethod normalizedOpMethod = handlerOperationMethod.get(); Object response = invokeOperation(normalizedOpMethod, normalizedOpMethod.getNormalizedArgs()); HandlerFunction handlerFunction = null; + + // filters added by HandlerDiscoverer need to go last, so save them + List> handlerFilterFunctionFilters = new ArrayList<>(); if (response instanceof HandlerFunction) { handlerFunction = (HandlerFunction) response; } else if (response instanceof HandlerDiscoverer.Result result) { handlerFunction = result.getHandlerFunction(); - result.getFilters().forEach(builder::filter); + handlerFilterFunctionFilters.addAll(result.getFilters()); } if (handlerFunction == null) { throw new IllegalStateException( @@ -221,6 +225,9 @@ public class RouterFunctionHolderFactory { translate(filterOperations, filterProperties.getName(), args, HandlerFilterFunction.class, builder::filter); }); + // HandlerDiscoverer filters need higher priority, so put them last + handlerFilterFunctionFilters.forEach(builder::filter); + builder.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, routeId); return builder.build(); diff --git a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java index f4f7675c..861b1694 100644 --- a/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java +++ b/spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/config/GatewayMvcPropertiesBeanDefinitionRegistrarTests.java @@ -122,7 +122,7 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests { predicate.accept(new AbstractRequestPredicatesVisitor() { @Override public void path(String pattern) { - assertThat(pattern).isEqualTo("/anything/listRoute3"); + assertThat(pattern).isEqualTo("/extra/anything/listRoute3"); } @Override @@ -181,7 +181,7 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests { @SuppressWarnings("unchecked") public void lbRouteWorks() { restClient.get() - .uri("/anything/listRoute3") + .uri("/extra/anything/listRoute3") .header("MyHeaderName", "MyHeaderVal") .exchange() .expectStatus() 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 5270b8cb..a91fe14d 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 @@ -38,9 +38,12 @@ spring.cloud.gateway.mvc: - id: listRoute3 uri: lb://httpbin predicates: - - Path=/anything/listRoute3 + - Path=/extra/anything/listRoute3 - Header=MyHeaderName,MyHeader.* filters: + - name: StripPrefix + args: + parts: 1 - name: AddRequestHeader args: name: X-Test From 0f3112077d0ac34eb594f735b42c1ca27a38bd30 Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Tue, 18 Mar 2025 15:46:14 +0800 Subject: [PATCH 11/17] update unit test Signed-off-by: jiangyuan --- .../factory/RetryGatewayFilterFactoryIntegrationTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 bacd256c..fb1439d1 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 @@ -130,6 +130,7 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest .exchange() .expectStatus() .isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(TestConfig.map.get("retry-with-backoff-timeout")).isNotNull().hasValue(2); } @Test @@ -398,7 +399,7 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest .filters(f -> f.prefixPath("/httpbin").retry(config -> { config.setRetries(3) .setBackoff(Duration.ofMillis(100), null, 2, true) - .setTimeout(Duration.ofMillis(100)); + .setTimeout(Duration.ofMillis(200)); })) .uri(uri)) From 2175fc1c8e374e361ef801b95c2ee00a79c0cd4d Mon Sep 17 00:00:00 2001 From: spring-builds Date: Tue, 18 Mar 2025 13:26:51 +0000 Subject: [PATCH 12/17] Bumping versions --- .../SpringCloudCircuitBreakerFilterFactoryTests.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java index 30eb9a8b..87c26cc6 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java @@ -246,9 +246,15 @@ public abstract class SpringCloudCircuitBreakerFilterFactoryTests extends BaseWe @Test public void filterPostFallback() { - testClient.post().uri("/post").body(BodyInserters.fromValue("hello")) - .header("Host", "www.circuitbreakerfallbackpost.org").exchange().expectStatus() - .isOk().expectBody().json("{\"body\":\"hello\"}"); + testClient.post() + .uri("/post") + .body(BodyInserters.fromValue("hello")) + .header("Host", "www.circuitbreakerfallbackpost.org") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .json("{\"body\":\"hello\"}"); } } From 263e8135582238256e2c416f627c0f3fb197ef51 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Tue, 18 Mar 2025 23:46:46 +0000 Subject: [PATCH 13/17] Update SNAPSHOT to 4.2.1 --- docs/modules/ROOT/partials/_configprops.adoc | 42 +++++++++---------- docs/pom.xml | 2 +- pom.xml | 8 ++-- spring-cloud-gateway-dependencies/pom.xml | 4 +- .../grpc/pom.xml | 2 +- .../http2/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- .../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 +- ...CloudCircuitBreakerFilterFactoryTests.java | 12 ++++-- 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, 48 insertions(+), 42 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 7a042b63..a8eed641 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -3,10 +3,10 @@ |spring.cloud.gateway.default-filters | | List of filter definitions that are applied to every route. |spring.cloud.gateway.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. -|spring.cloud.gateway.discovery.locator.filters | | +|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. |spring.cloud.gateway.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.discovery.locator.predicates | | +|spring.cloud.gateway.discovery.locator.predicates | | |spring.cloud.gateway.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.discovery.locator.url-expression | `+++'lb://'+serviceId+++` | SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId. |spring.cloud.gateway.enabled | `+++true+++` | Enables gateway functionality. @@ -20,7 +20,7 @@ |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.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|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. @@ -29,15 +29,15 @@ |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.headers | | -|spring.cloud.gateway.filter.remove-hop-by-hop.order | `+++0+++` | +|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.default-key-resolver | | -|spring.cloud.gateway.filter.request-rate-limiter.default-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. |spring.cloud.gateway.filter.retry.enabled | `+++true+++` | Enables the retry filter. @@ -47,16 +47,16 @@ |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.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.disable | | -|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | +|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.disable | | +|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.frame-options | `+++DENY+++` | -|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+++` | +|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | +|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+++` | |spring.cloud.gateway.filter.set-path.enabled | `+++true+++` | Enables the set-path filter. |spring.cloud.gateway.filter.set-request-header.enabled | `+++true+++` | Enables the set-request-header filter. |spring.cloud.gateway.filter.set-request-host-header.enabled | `+++true+++` | Enables the set-request-host-header filter. @@ -76,7 +76,7 @@ |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.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.globalcors.cors-configurations | | |spring.cloud.gateway.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. |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. @@ -113,7 +113,7 @@ |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.use404 | `+++false+++` | +|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | |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. @@ -161,7 +161,7 @@ |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.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.config | | |spring.cloud.gateway.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. |spring.cloud.gateway.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.redis-rate-limiter.replenish-rate-header | `+++X-RateLimit-Replenish-Rate+++` | The name of the header that returns the replenish rate configuration. @@ -172,7 +172,7 @@ |spring.cloud.gateway.route-refresh-listener.enabled | `+++true+++` | If RouteRefreshListener should be turned on. |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.streaming-media-types | | |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. @@ -186,4 +186,4 @@ |spring.cloud.gateway.x-forwarded.proto-append | `+++true+++` | If appending X-Forwarded-Proto as a list is enabled. |spring.cloud.gateway.x-forwarded.proto-enabled | `+++true+++` | If X-Forwarded-Proto is enabled. -|=== +|=== \ No newline at end of file diff --git a/docs/pom.xml b/docs/pom.xml index df489971..b5f9c482 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1-SNAPSHOT + 4.2.1 spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index 87438173..9506a997 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1-SNAPSHOT + 4.2.1 pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.2.1-SNAPSHOT + 4.2.1 @@ -55,8 +55,8 @@ 1.0.8.RELEASE 17 2.3.0 - 3.2.1-SNAPSHOT - 4.2.1-SNAPSHOT + 3.2.1 + 4.2.1 diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 6d255037..12006ace 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.2.1-SNAPSHOT + 4.2.1 spring-cloud-gateway-dependencies - 4.2.1-SNAPSHOT + 4.2.1 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 606d6cf6..0c8a671c 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index f833c541..d62efe0d 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.2.1-SNAPSHOT + 4.2.1 .. 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 c79551c2..d8ccedaf 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index e9bf2a3c..69787cdc 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index ed68626d..603d949a 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 41884109..9ee987ab 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index ba17bdf7..d2db5be5 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.2.1-SNAPSHOT + 4.2.1 .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index c365ed4b..12d05627 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.2.1-SNAPSHOT + 4.2.1 .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java index 30eb9a8b..87c26cc6 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java @@ -246,9 +246,15 @@ public abstract class SpringCloudCircuitBreakerFilterFactoryTests extends BaseWe @Test public void filterPostFallback() { - testClient.post().uri("/post").body(BodyInserters.fromValue("hello")) - .header("Host", "www.circuitbreakerfallbackpost.org").exchange().expectStatus() - .isOk().expectBody().json("{\"body\":\"hello\"}"); + testClient.post() + .uri("/post") + .body(BodyInserters.fromValue("hello")) + .header("Host", "www.circuitbreakerfallbackpost.org") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .json("{\"body\":\"hello\"}"); } } diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index fe8b8ece..31371a1c 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.2.1-SNAPSHOT + 4.2.1 .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index a2c8eba8..66d548ad 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.2.1-SNAPSHOT + 4.2.1 .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index f32a7980..5399cc25 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.2.1-SNAPSHOT + 4.2.1 .. spring-cloud-starter-gateway From 0ee6a5d6da432c7d7378329d8281c160e32e1bea Mon Sep 17 00:00:00 2001 From: spring-builds Date: Tue, 18 Mar 2025 23:49:59 +0000 Subject: [PATCH 14/17] Going back to snapshots --- docs/modules/ROOT/partials/_configprops.adoc | 42 +++++++++---------- docs/pom.xml | 2 +- pom.xml | 8 ++-- spring-cloud-gateway-dependencies/pom.xml | 4 +- .../grpc/pom.xml | 2 +- .../http2/pom.xml | 2 +- .../mvc-failure-analyzer/pom.xml | 2 +- .../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 +- ...CloudCircuitBreakerFilterFactoryTests.java | 12 ++---- 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, 42 insertions(+), 48 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index a8eed641..7a042b63 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -3,10 +3,10 @@ |spring.cloud.gateway.default-filters | | List of filter definitions that are applied to every route. |spring.cloud.gateway.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. -|spring.cloud.gateway.discovery.locator.filters | | +|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. |spring.cloud.gateway.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.discovery.locator.predicates | | +|spring.cloud.gateway.discovery.locator.predicates | | |spring.cloud.gateway.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.discovery.locator.url-expression | `+++'lb://'+serviceId+++` | SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId. |spring.cloud.gateway.enabled | `+++true+++` | Enables gateway functionality. @@ -20,7 +20,7 @@ |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.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|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. @@ -29,15 +29,15 @@ |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.headers | | -|spring.cloud.gateway.filter.remove-hop-by-hop.order | `+++0+++` | +|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.default-key-resolver | | -|spring.cloud.gateway.filter.request-rate-limiter.default-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. |spring.cloud.gateway.filter.retry.enabled | `+++true+++` | Enables the retry filter. @@ -47,16 +47,16 @@ |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.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.disable | | -|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | +|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.disable | | +|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.frame-options | `+++DENY+++` | -|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+++` | +|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | +|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+++` | |spring.cloud.gateway.filter.set-path.enabled | `+++true+++` | Enables the set-path filter. |spring.cloud.gateway.filter.set-request-header.enabled | `+++true+++` | Enables the set-request-header filter. |spring.cloud.gateway.filter.set-request-host-header.enabled | `+++true+++` | Enables the set-request-host-header filter. @@ -76,7 +76,7 @@ |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.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.globalcors.cors-configurations | | |spring.cloud.gateway.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. |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. @@ -113,7 +113,7 @@ |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.use404 | `+++false+++` | +|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | |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. @@ -161,7 +161,7 @@ |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.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.config | | |spring.cloud.gateway.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. |spring.cloud.gateway.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.redis-rate-limiter.replenish-rate-header | `+++X-RateLimit-Replenish-Rate+++` | The name of the header that returns the replenish rate configuration. @@ -172,7 +172,7 @@ |spring.cloud.gateway.route-refresh-listener.enabled | `+++true+++` | If RouteRefreshListener should be turned on. |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.streaming-media-types | | |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. @@ -186,4 +186,4 @@ |spring.cloud.gateway.x-forwarded.proto-append | `+++true+++` | If appending X-Forwarded-Proto as a list is enabled. |spring.cloud.gateway.x-forwarded.proto-enabled | `+++true+++` | If X-Forwarded-Proto is enabled. -|=== \ No newline at end of file +|=== diff --git a/docs/pom.xml b/docs/pom.xml index b5f9c482..df489971 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1 + 4.2.1-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index 9506a997..87438173 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1 + 4.2.1-SNAPSHOT pom Spring Cloud Gateway @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.2.1 + 4.2.1-SNAPSHOT @@ -55,8 +55,8 @@ 1.0.8.RELEASE 17 2.3.0 - 3.2.1 - 4.2.1 + 3.2.1-SNAPSHOT + 4.2.1-SNAPSHOT diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 12006ace..6d255037 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.2.1 + 4.2.1-SNAPSHOT spring-cloud-gateway-dependencies - 4.2.1 + 4.2.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 0c8a671c..606d6cf6 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index d62efe0d..f833c541 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.2.1 + 4.2.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 d8ccedaf..c79551c2 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index 69787cdc..e9bf2a3c 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index 603d949a..ed68626d 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 9ee987ab..41884109 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index d2db5be5..ba17bdf7 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.2.1 + 4.2.1-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index 12d05627..c365ed4b 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.2.1 + 4.2.1-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java index 87c26cc6..30eb9a8b 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java @@ -246,15 +246,9 @@ public abstract class SpringCloudCircuitBreakerFilterFactoryTests extends BaseWe @Test public void filterPostFallback() { - testClient.post() - .uri("/post") - .body(BodyInserters.fromValue("hello")) - .header("Host", "www.circuitbreakerfallbackpost.org") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .json("{\"body\":\"hello\"}"); + testClient.post().uri("/post").body(BodyInserters.fromValue("hello")) + .header("Host", "www.circuitbreakerfallbackpost.org").exchange().expectStatus() + .isOk().expectBody().json("{\"body\":\"hello\"}"); } } diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index 31371a1c..fe8b8ece 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.2.1 + 4.2.1-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index 66d548ad..a2c8eba8 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.2.1 + 4.2.1-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index 5399cc25..f32a7980 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.2.1 + 4.2.1-SNAPSHOT .. spring-cloud-starter-gateway From 50bf1d72a0b87ab232749a13e3f5d7a51b68caee Mon Sep 17 00:00:00 2001 From: spring-builds Date: Tue, 18 Mar 2025 23:50:00 +0000 Subject: [PATCH 15/17] Bumping versions to 4.2.2-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 +- .../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 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index df489971..6819860b 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1-SNAPSHOT + 4.2.2-SNAPSHOT spring-cloud-gateway-docs jar diff --git a/pom.xml b/pom.xml index 87438173..c25bbd63 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-gateway - 4.2.1-SNAPSHOT + 4.2.2-SNAPSHOT pom Spring Cloud Gateway diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 6d255037..6064d8b6 100644 --- a/spring-cloud-gateway-dependencies/pom.xml +++ b/spring-cloud-gateway-dependencies/pom.xml @@ -11,7 +11,7 @@ spring-cloud-gateway-dependencies - 4.2.1-SNAPSHOT + 4.2.2-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 606d6cf6..7cad9cdc 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/http2/pom.xml b/spring-cloud-gateway-integration-tests/http2/pom.xml index f833c541..6e53c34a 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.2.1-SNAPSHOT + 4.2.2-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 c79551c2..05b46aa5 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-gateway-integration-tests/pom.xml b/spring-cloud-gateway-integration-tests/pom.xml index e9bf2a3c..d8b10218 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-gateway-mvc/pom.xml b/spring-cloud-gateway-mvc/pom.xml index ed68626d..7a38b262 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml index 41884109..135316d2 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-gateway-server-mvc/pom.xml b/spring-cloud-gateway-server-mvc/pom.xml index ba17bdf7..2c725c88 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. spring-cloud-gateway-server-mvc diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml index c365ed4b..8abe6b8e 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. spring-cloud-gateway-server diff --git a/spring-cloud-gateway-webflux/pom.xml b/spring-cloud-gateway-webflux/pom.xml index fe8b8ece..901ed835 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. diff --git a/spring-cloud-starter-gateway-mvc/pom.xml b/spring-cloud-starter-gateway-mvc/pom.xml index a2c8eba8..d5e924ae 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. spring-cloud-starter-gateway-mvc diff --git a/spring-cloud-starter-gateway/pom.xml b/spring-cloud-starter-gateway/pom.xml index f32a7980..572ce693 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT .. spring-cloud-starter-gateway From a5bd46a91dc798673c3a59fc9a7a53d6b3996d92 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Tue, 18 Mar 2025 23:51:12 +0000 Subject: [PATCH 16/17] Bumping dependency versions after release --- pom.xml | 6 +++--- spring-cloud-gateway-dependencies/pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index c25bbd63..b493fc0f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.springframework.cloud spring-cloud-build - 4.2.1-SNAPSHOT + 4.2.2-SNAPSHOT @@ -55,8 +55,8 @@ 1.0.8.RELEASE 17 2.3.0 - 3.2.1-SNAPSHOT - 4.2.1-SNAPSHOT + 3.2.2-SNAPSHOT + 4.2.2-SNAPSHOT diff --git a/spring-cloud-gateway-dependencies/pom.xml b/spring-cloud-gateway-dependencies/pom.xml index 6064d8b6..d1da19ac 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.2.1-SNAPSHOT + 4.2.2-SNAPSHOT From 0c1b54926d41a0929a9a3ee877849d08ce3cccd9 Mon Sep 17 00:00:00 2001 From: spring-builds Date: Thu, 20 Mar 2025 09:57:45 +0000 Subject: [PATCH 17/17] Bumping versions --- docs/modules/ROOT/partials/_configprops.adoc | 42 +++++++++---------- ...CloudCircuitBreakerFilterFactoryTests.java | 12 ++++-- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 7a042b63..a8eed641 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -3,10 +3,10 @@ |spring.cloud.gateway.default-filters | | List of filter definitions that are applied to every route. |spring.cloud.gateway.discovery.locator.enabled | `+++false+++` | Flag that enables DiscoveryClient gateway integration. -|spring.cloud.gateway.discovery.locator.filters | | +|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. |spring.cloud.gateway.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.discovery.locator.predicates | | +|spring.cloud.gateway.discovery.locator.predicates | | |spring.cloud.gateway.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.discovery.locator.url-expression | `+++'lb://'+serviceId+++` | SpEL expression that create the uri for each route, defaults to: 'lb://'+serviceId. |spring.cloud.gateway.enabled | `+++true+++` | Enables gateway functionality. @@ -20,7 +20,7 @@ |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.enabled | `+++false+++` | Enables the local-response-cache filter. -|spring.cloud.gateway.filter.local-response-cache.request.no-cache-strategy | `+++skip-update-cache-entry+++` | +|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. @@ -29,15 +29,15 @@ |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.headers | | -|spring.cloud.gateway.filter.remove-hop-by-hop.order | `+++0+++` | +|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.default-key-resolver | | -|spring.cloud.gateway.filter.request-rate-limiter.default-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. |spring.cloud.gateway.filter.retry.enabled | `+++true+++` | Enables the retry filter. @@ -47,16 +47,16 @@ |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.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.disable | | -|spring.cloud.gateway.filter.secure-headers.download-options | `+++noopen+++` | +|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.disable | | +|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.frame-options | `+++DENY+++` | -|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+++` | +|spring.cloud.gateway.filter.secure-headers.frame-options | `+++DENY+++` | +|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+++` | |spring.cloud.gateway.filter.set-path.enabled | `+++true+++` | Enables the set-path filter. |spring.cloud.gateway.filter.set-request-header.enabled | `+++true+++` | Enables the set-request-header filter. |spring.cloud.gateway.filter.set-request-host-header.enabled | `+++true+++` | Enables the set-request-host-header filter. @@ -76,7 +76,7 @@ |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.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.globalcors.cors-configurations | | |spring.cloud.gateway.handler-mapping.order | `+++1+++` | The order of RoutePredicateHandlerMapping. |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. @@ -113,7 +113,7 @@ |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.use404 | `+++false+++` | +|spring.cloud.gateway.loadbalancer.use404 | `+++false+++` | |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. @@ -161,7 +161,7 @@ |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.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.config | | |spring.cloud.gateway.redis-rate-limiter.include-headers | `+++true+++` | Whether or not to include headers containing rate limiter information, defaults to true. |spring.cloud.gateway.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.redis-rate-limiter.replenish-rate-header | `+++X-RateLimit-Replenish-Rate+++` | The name of the header that returns the replenish rate configuration. @@ -172,7 +172,7 @@ |spring.cloud.gateway.route-refresh-listener.enabled | `+++true+++` | If RouteRefreshListener should be turned on. |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.streaming-media-types | | |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. @@ -186,4 +186,4 @@ |spring.cloud.gateway.x-forwarded.proto-append | `+++true+++` | If appending X-Forwarded-Proto as a list is enabled. |spring.cloud.gateway.x-forwarded.proto-enabled | `+++true+++` | If X-Forwarded-Proto is enabled. -|=== +|=== \ No newline at end of file diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java index 30eb9a8b..87c26cc6 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SpringCloudCircuitBreakerFilterFactoryTests.java @@ -246,9 +246,15 @@ public abstract class SpringCloudCircuitBreakerFilterFactoryTests extends BaseWe @Test public void filterPostFallback() { - testClient.post().uri("/post").body(BodyInserters.fromValue("hello")) - .header("Host", "www.circuitbreakerfallbackpost.org").exchange().expectStatus() - .isOk().expectBody().json("{\"body\":\"hello\"}"); + testClient.post() + .uri("/post") + .body(BodyInserters.fromValue("hello")) + .header("Host", "www.circuitbreakerfallbackpost.org") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .json("{\"body\":\"hello\"}"); } }