From 2a567de2518c82af1ed8f025c96ced0cb020c415 Mon Sep 17 00:00:00 2001 From: Spencer Gibb Date: Tue, 20 Mar 2018 23:23:58 -0400 Subject: [PATCH] Moves Retry filter to new style configuration. fixes gh-224 --- .../factory/RetryGatewayFilterFactory.java | 57 +++++++------------ .../route/builder/GatewayFilterSpec.java | 19 +------ ...yGatewayFilterFactoryIntegrationTests.java | 39 +++++++++++-- 3 files changed, 56 insertions(+), 59 deletions(-) diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java index 0502d67f..358c3158 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java @@ -17,8 +17,8 @@ package org.springframework.cloud.gateway.filter.factory; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.function.Predicate; @@ -26,43 +26,20 @@ import reactor.retry.Repeat; import reactor.retry.RepeatContext; import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus.Series; -import org.springframework.tuple.Tuple; import org.springframework.util.Assert; import org.springframework.web.server.ServerWebExchange; -public class RetryGatewayFilterFactory implements GatewayFilterFactory { - @Override - public GatewayFilter apply(Tuple args) { - Retry retry = new Retry(); +public class RetryGatewayFilterFactory extends AbstractGatewayFilterFactory { - if (args.hasFieldName("retries")) { - retry.retries(args.getInt("retries")); - } - - // TODO: list of statusSeries - if (args.hasFieldName("statusSeries")) { - int statusSeries = args.getInt("statusSeries"); - retry.series(Series.valueOf(statusSeries)); - } - - // TODO: list of status - if (args.hasFieldName("status")) { - retry.statuses(ServerWebExchangeUtils.parse(args.getRawString("status"))); - } - - // TODO: list of methods - if (args.hasFieldName("method")) { - retry.methods(HttpMethod.resolve(args.getString("method").toUpperCase())); - } - - return apply(retry); + public RetryGatewayFilterFactory() { + super(Retry.class); } - public GatewayFilter apply(Retry retry) { + @Override + public GatewayFilter apply(Retry retry) { retry.validate(); Predicate> predicate = context -> { @@ -93,37 +70,43 @@ public class RetryGatewayFilterFactory implements GatewayFilterFactory { repeat.withApplicationContext(exchange)).next(); } + private static List toList(T item) { + ArrayList list = new ArrayList<>(); + list.add(item); + return list; + } + public static class Retry { private int retries = 3; - private List series = Collections.singletonList(Series.SERVER_ERROR); + private List series = toList(Series.SERVER_ERROR); - private List statuses = Collections.emptyList(); + private List statuses = new ArrayList<>(); - private List methods = Collections.singletonList(HttpMethod.GET); + private List methods = toList(HttpMethod.GET); - public Retry retries(int retries) { + public Retry setRetries(int retries) { this.retries = retries; return this; } - public Retry series(Series... series) { + public Retry setSeries(Series... series) { this.series = Arrays.asList(series); return this; } - public Retry statuses(HttpStatus... statuses) { + public Retry setStatuses(HttpStatus... statuses) { this.statuses = Arrays.asList(statuses); return this; } - public Retry methods(HttpMethod... methods) { + public Retry setMethods(HttpMethod... methods) { this.methods = Arrays.asList(methods); return this; } public Retry allMethods() { - return methods(HttpMethod.values()); + return setMethods(HttpMethod.values()); } public void validate() { diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index d0c79ac4..ce9561f9 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -196,24 +196,11 @@ public class GatewayFilterSpec extends UriSpec { */ public GatewayFilterSpec retry(int retries) { return filter(getBean(RetryGatewayFilterFactory.class) - .apply(new RetryGatewayFilterFactory.Retry() - .retries(retries))); + .apply(retry -> retry.setRetries(retries))); } - /** - * @param retries max number of retries - * @param httpStatusSeries the http status series that is retryable - * @param httpMethod the http method that is retryable - */ - public GatewayFilterSpec retry(int retries, HttpStatus.Series httpStatusSeries, HttpMethod httpMethod) { - return retry(new RetryGatewayFilterFactory.Retry() - .retries(retries) - .series(httpStatusSeries) - .methods(httpMethod)); - } - - public GatewayFilterSpec retry(RetryGatewayFilterFactory.Retry retry) { - return filter(getBean(RetryGatewayFilterFactory.class).apply(retry)); + public GatewayFilterSpec retry(Consumer retryConsumer) { + return filter(getBean(RetryGatewayFilterFactory.class).apply(retryConsumer)); } public GatewayFilterSpec retry(Repeat repeat) { diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java index 772a6d42..7bda5d92 100644 --- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java +++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java @@ -25,15 +25,18 @@ import org.apache.commons.logging.LogFactory; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.cloud.gateway.test.BaseWebClientTests; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; -import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.HttpHeaders; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -54,6 +57,16 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest .expectBody(String.class).isEqualTo("3"); } + @Test + public void retryFilterGetJavaDsl() { + testClient.get() + .uri("/retry?key=getjava&count=2") + .header(HttpHeaders.HOST, "www.retryjava.org") + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo("2"); + } + @Test //TODO: support post public void retryFilterPost() { @@ -71,18 +84,32 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest public static class TestConfig { Log log = LogFactory.getLog(getClass()); + @Value("${test.uri}") + private String uri; + ConcurrentHashMap map = new ConcurrentHashMap<>(); @RequestMapping("/httpbin/retry") - public String retry(@RequestParam("key") String key) { - AtomicInteger count = map.computeIfAbsent(key, s -> new AtomicInteger()); - int i = count.incrementAndGet(); + public String retry(@RequestParam("key") String key, @RequestParam(name = "count", defaultValue = "3") int count) { + AtomicInteger num = map.computeIfAbsent(key, s -> new AtomicInteger()); + int i = num.incrementAndGet(); log.warn("Retry count: "+i); - if (i < 3) { + if (i < count) { throw new RuntimeException("temporarily broken"); } return String.valueOf(i); } + + + @Bean + public RouteLocator hystrixRouteLocator(RouteLocatorBuilder builder) { + return builder.routes() + .route("retry_java", r -> r.host("**.retryjava.org") + .filters(f -> f.prefixPath("/httpbin") + .retry(config -> config.setRetries(2))) + .uri(uri)) + .build(); + } } }