From 67f95244be7b44284ea171cee060356260971996 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 22 Apr 2022 15:35:18 +1000 Subject: [PATCH] Adds a method to nest boolean predicates Spring Cloud Gateway supports complicated boolean predicates like: (query("a") || query("b")) && (host("x") || host("y)) But lacked a Java API to express this. This new methods allows the above: r.query("a").or().query("b").and().nested(p -> r.host("x").or().host("y") ) Fixes gh-2598 --- .../gateway/route/builder/BooleanSpec.java | 17 ++++++++++++++++ ...edicateHandlerMappingIntegrationTests.java | 20 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/BooleanSpec.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/BooleanSpec.java index f6399138..f993106a 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/BooleanSpec.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/BooleanSpec.java @@ -115,6 +115,10 @@ public class BooleanSpec extends UriSpec { return fn.apply(new NotOpSpec(this.routeBuilder, this.builder, this.operator)); } + public BooleanSpec nested(Function fn) { + return fn.apply(new NestedOpSpec(this.routeBuilder, this.builder, this.operator)); + } + } public static class NotOpSpec extends BooleanOpSpec { @@ -131,4 +135,17 @@ public class BooleanSpec extends UriSpec { } + public static class NestedOpSpec extends BooleanOpSpec { + + NestedOpSpec(Route.AsyncBuilder routeBuilder, RouteLocatorBuilder.Builder builder, Operator operator) { + super(routeBuilder, builder, operator); + } + + @Override + public BooleanSpec asyncPredicate(AsyncPredicate predicate) { + return super.asyncPredicate(predicate); + } + + } + } diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMappingIntegrationTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMappingIntegrationTests.java index 403ef423..182623ca 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMappingIntegrationTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/handler/RoutePredicateHandlerMappingIntegrationTests.java @@ -94,6 +94,18 @@ public class RoutePredicateHandlerMappingIntegrationTests extends BaseWebClientT .isEqualTo("hasquery"); } + @Test + public void andNestedOrQuery1() { + testClient.get().uri("/andnestedquery?query1=hasquery1").exchange().expectBody(String.class) + .isEqualTo("hasquery1,notsupplied"); + } + + @Test + public void andNestedOrQuery2() { + testClient.get().uri("/andnestedquery?query2=hasquery2").exchange().expectBody(String.class) + .isEqualTo("notsupplied,hasquery2"); + } + @EnableAutoConfiguration @SpringBootConfiguration @Import(DefaultTestConfig.class) @@ -108,6 +120,12 @@ public class RoutePredicateHandlerMappingIntegrationTests extends BaseWebClientT return myquery; } + @GetMapping("/httpbin/andnestedquery") + String andnotquery(@RequestParam(name = "query1", defaultValue = "notsupplied") String query1, + @RequestParam(name = "query2", defaultValue = "notsupplied") String query2) { + return query1 + "," + query2; + } + @GetMapping("/httpbin/hasquery") String hasquery() { return "hasquery"; @@ -128,6 +146,8 @@ public class RoutePredicateHandlerMappingIntegrationTests extends BaseWebClientT .query("myquery") .filters(f -> f.setPath("/httpbin/hasquery")) .uri(uri)) + .route("and_nested_query1_or_query2", r -> r.path("/andnestedquery").and().nested(p -> p.query("query1").or().query("query2")) + .filters(f -> f.prefixPath("/httpbin")).uri(uri)) .build(); }