diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index 91d23e32..70d1be17 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -1501,6 +1501,39 @@ Instead, it should throw an `Exception` or signal an error (for example, through WARNING: When using the retry filter with any HTTP method with a body, the body will be cached and the gateway will become memory constrained. The body is cached in a request attribute defined by `ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR`. The type of the object is a `org.springframework.core.io.buffer.DataBuffer`. +A simplified "shortcut" notation can be added with a single `status` and `method`. + +The following two examples are equivalent: + +.application.yml +==== +[source,yaml] +---- +spring: + cloud: + gateway: + routes: + - id: retry_route + uri: https://example.org + filters: + - name: Retry + args: + retries: 3 + statuses: INTERNAL_SERVER_ERROR + methods: GET + backoff: + firstBackoff: 10ms + maxBackoff: 50ms + factor: 2 + basedOnPreviousValue: false + + - id: retryshortcut_route + uri: https://example.org + filters: + - Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false +---- +==== + === The `RequestSize` `GatewayFilter` Factory When the request size is greater than the permissible limit, the `RequestSize` `GatewayFilter` factory can restrict a request from reaching the downstream service. 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 707c0f73..039430ce 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 @@ -66,6 +66,12 @@ public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory(Arrays.asList(items)); } + @Override + public List shortcutFieldOrder() { + return Arrays.asList("retries", "statuses", "methods", "backoff.firstBackoff", "backoff.maxBackoff", + "backoff.factor", "backoff.basedOnPreviousValue"); + } + @Override public GatewayFilter apply(RetryConfig retryConfig) { retryConfig.validate(); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java index 7e773928..c3e370c0 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocatorTests.java @@ -82,6 +82,36 @@ public class RouteDefinitionRouteLocatorTests { }).expectComplete().verify(); } + @Test + public void simpleRetryDefinitionLoads() { + List predicates = Arrays.asList(new HostRoutePredicateFactory()); + List gatewayFilterFactories = Arrays.asList(new RetryGatewayFilterFactory()); + GatewayProperties gatewayProperties = new GatewayProperties(); + gatewayProperties.setRoutes(Arrays.asList(new RouteDefinition() { + { + setId("simple"); + setUri(URI.create("https://foo.example.com")); + setPredicates(Arrays.asList(new PredicateDefinition("Host=*.example.com"))); + setFilters(Arrays.asList(new FilterDefinition("Retry=3,INTERNAL_SERVER_ERROR,GET"))); + } + })); + + PropertiesRouteDefinitionLocator routeDefinitionLocator = new PropertiesRouteDefinitionLocator( + gatewayProperties); + RouteDefinitionRouteLocator routeDefinitionRouteLocator = new RouteDefinitionRouteLocator( + new CompositeRouteDefinitionLocator(Flux.just(routeDefinitionLocator)), predicates, + gatewayFilterFactories, gatewayProperties, new ConfigurationService(null, () -> null, () -> null)); + + StepVerifier.create(routeDefinitionRouteLocator.getRoutes()).assertNext(route -> { + List filters = route.getFilters(); + assertThat(filters).hasSize(1); + assertThat(getFilterClassName(filters.get(0))).contains("Retry"); + assertThat(filters.get(0).toString()).contains("retries = 3"); + assertThat(filters.get(0).toString()).contains("series = list[SERVER_ERROR]"); + assertThat(filters.get(0).toString()).contains("methods = list[GET]"); + }).expectComplete().verify(); + } + @Test public void contextLoadsWithErrorRecovery() { List predicates = Arrays.asList(new HostRoutePredicateFactory());