Skip to content

Commit 563a0ab

Browse files
committed
Adds GatewayRequestPredicates.query()
1 parent 7a419c8 commit 563a0ab

File tree

4 files changed

+94
-6
lines changed

4 files changed

+94
-6
lines changed

docs/modules/ROOT/pages/spring-cloud-gateway-server-mvc/gateway-request-predicates.adoc

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,6 @@ Map<String, Object> uriVariables = MvcUtils.getUriTemplateVariables(request);
390390
String segment = uriVariables.get("segment");
391391
----
392392

393-
////
394-
TODO: query predicate
395393
[[query-request-predicate]]
396394
== The Query Request Predicate
397395

@@ -411,6 +409,26 @@ spring:
411409
- Query=green
412410
----
413411

412+
.GatewaySampleApplication.java
413+
[source,java]
414+
----
415+
import org.springframework.http.HttpMethod;
416+
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
417+
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
418+
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;
419+
420+
@Configuration
421+
class RouteConfiguration {
422+
423+
@Bean
424+
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
425+
return route("query_route")
426+
.route(query("green"), http("https://example.org"))
427+
.build();
428+
}
429+
}
430+
----
431+
414432
The preceding route matches if the request contained a `green` query parameter.
415433

416434
.application.yml
@@ -426,8 +444,29 @@ spring:
426444
- Query=red, gree.
427445
----
428446

447+
.GatewaySampleApplication.java
448+
[source,java]
449+
----
450+
import org.springframework.http.HttpMethod;
451+
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
452+
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
453+
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;
454+
455+
@Configuration
456+
class RouteConfiguration {
457+
458+
@Bean
459+
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
460+
return route("query_route")
461+
.route(query("red", "gree."), http("https://example.org"))
462+
.build();
463+
}
464+
}
465+
----
466+
429467
The preceding route matches if the request contained a `red` query parameter whose value matched the `gree.` regexp, so `green` and `greet` would match.
430468

469+
////
431470
TODO: remoteAddr predicate
432471
[[remoteaddr-request-predicate]]
433472
== The RemoteAddr Request Predicate
@@ -511,7 +550,7 @@ RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
511550
[[weight-request-predicate]]
512551
== The Weight Request Predicate
513552

514-
The `Weight` route predicate factory takes two arguments: `group` and `weight` (an int). The weights are calculated per group.
553+
The `Weight` route predicate factory takes two arguments: `group` and `weight` (an `int`). The weights are calculated per group.
515554
The following example configures a weight route predicate:
516555

517556
.application.yml
@@ -554,7 +593,7 @@ class RouteConfiguration {
554593
}
555594
----
556595

557-
This route would forward ~80% of traffic to https://weighthigh.org and ~20% of traffic to https://weightlow.org
596+
This route would forward ~80% of traffic to https://weighthigh.org and ~20% of traffic to https://weightlow.org.
558597

559598
////
560599
TODO: XForwardedRemoteAddr predicate

spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/ProxyExchangeHandlerFunction.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,10 @@ public ServerResponse handle(ServerRequest serverRequest) {
6969
boolean encoded = containsEncodedQuery(serverRequest.uri());
7070
// @formatter:off
7171
URI url = UriComponentsBuilder.fromUri(serverRequest.uri())
72-
// .uri(routeUri)
7372
.scheme(uri.getScheme())
7473
.host(uri.getHost())
7574
.port(uri.getPort())
76-
.queryParams(serverRequest.params())
75+
.replaceQueryParams(serverRequest.params())
7776
.build(encoded)
7877
.toUri();
7978
// @formatter:on

spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/predicate/GatewayRequestPredicates.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,32 @@ public static RequestPredicate path(String... patterns) {
186186
return requestPredicate;
187187
}
188188

189+
/**
190+
* Return a {@code RequestPredicate} that tests the presence of a request parameter.
191+
* @param param the name of the query parameter
192+
* @return a predicate that tests for the presence of a given param
193+
*/
194+
@Shortcut
195+
public static RequestPredicate query(String param) {
196+
return query(param, null);
197+
}
198+
199+
/**
200+
* Return a {@code RequestPredicate} that tests the presence of a request parameter if
201+
* the regexp is empty, or, otherwise finds if any value of the parameter matches the
202+
* regexp.
203+
* @param param the name of the query parameter
204+
* @param regexp an optional regular expression to match.
205+
* @return a predicate that tests for the given param and regexp.
206+
*/
207+
@Shortcut
208+
public static RequestPredicate query(String param, String regexp) {
209+
if (!StringUtils.hasText(regexp)) {
210+
return request -> request.param(param).isPresent();
211+
}
212+
return request -> request.param(param).stream().anyMatch(value -> value.matches(regexp));
213+
}
214+
189215
public static <T> RequestPredicate readBody(Class<T> inClass, Predicate<T> predicate) {
190216
return new ReadBodyPredicate<>(inClass, predicate);
191217
}

spring-cloud-gateway-server-mvc/src/test/java/org/springframework/cloud/gateway/server/mvc/ServerMvcIntegrationTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.cookie;
120120
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.header;
121121
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;
122+
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;
122123
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.readBody;
123124
import static org.springframework.cloud.gateway.server.mvc.test.TestUtils.getMap;
124125
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
@@ -605,6 +606,19 @@ public void forwardNon200StatusWorks() {
605606
.isEqualTo("hello2");
606607
}
607608

609+
@Test
610+
@SuppressWarnings("rawtypes")
611+
public void queryParamWorks() {
612+
restClient.get().uri("/get?foo=bar").exchange().expectStatus().isOk().expectBody(Map.class)
613+
.consumeWith(result -> {
614+
Map responseBody = result.getResponseBody();
615+
assertThat(responseBody).containsKey("args");
616+
Map args = getMap(responseBody, "args");
617+
assertThat(args).containsKey("foo");
618+
assertThat(args.get("foo")).isEqualTo("bar");
619+
});
620+
}
621+
608622
@SpringBootConfiguration
609623
@EnableAutoConfiguration
610624
@LoadBalancerClient(name = "httpbin", configuration = TestLoadBalancerConfig.Httpbin.class)
@@ -1126,6 +1140,16 @@ public RouterFunction<ServerResponse> gatewayRouterFunctionsForwardNon200Status(
11261140
// @formatter:on
11271141
}
11281142

1143+
@Bean
1144+
public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
1145+
// @formatter:off
1146+
return route("testqueryparam")
1147+
.route(query("foo", "bar"), http())
1148+
.before(new HttpbinUriResolver())
1149+
.build();
1150+
// @formatter:on
1151+
}
1152+
11291153
private Predicate<Event> eventPredicate(String foo) {
11301154
return new Predicate<>() {
11311155
@Override

0 commit comments

Comments
 (0)