Gateway Request Predicates

Spring Cloud Gateway MVC 作为 Spring WebMvc.fn HandlerMapping 基础架构的一部分匹配路由。Spring Cloud Gateway 重用了 WebMvc.fn 中的许多 RequestPredicate 实现,并包含其他自定义 RequestPredicate 实现。所有这些谓词都匹配 HTTP 请求的不同属性。您可以使用 RequestPredicate.and()RequestPredicate.or() 方法组合多个路由谓词工厂。

Spring Cloud Gateway MVC matches routes as part of the Spring WebMvc.fn HandlerMapping infrastructure. Spring Cloud Gateway reuses many RequestPredicate implementations from WebMvc.fn and includes other custom RequestPredicate implementations All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with the RequestPredicate.and() and RequestPredicate.or() methods.

The After Request Predicate

After 路由谓词工厂接受一个参数,即一个 datetime(它是 java ZonedDateTime)。此谓词匹配在指定 datetime 之后发生的请求。以下示例配置一个 after 路由谓词:

The After route predicate factory takes one parameter, a datetime (which is a java ZonedDateTime). This predicate matches requests that happen after the specified datetime. The following example configures an after route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: after_route
          uri: https://example.org
          predicates:
          - After=2017-01-20T17:42:47.789-07:00[America/Denver]
GatewaySampleApplication.java
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.after;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsAfter() {
		return route("after_route")
			.route(after(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
			.build();
    }
}

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后发送的任何请求。

This route matches any request made after Jan 20, 2017 17:42 Mountain Time (Denver).

The Before Request Predicate

Before 路由谓词工厂接受一个参数,即一个 datetime(它是 java ZonedDateTime)。此谓词匹配在指定 datetime 之前发生的请求。以下示例配置一个 before 路由谓词:

The Before route predicate factory takes one parameter, a datetime (which is a java ZonedDateTime). This predicate matches requests that happen before the specified datetime. The following example configures a before route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: before_route
          uri: https://example.org
          predicates:
          - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
GatewaySampleApplication.java
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.before;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsBefore() {
		return route("before_route")
			.route(before(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
			.build();
    }
}

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之前发送的任何请求。

This route matches any request made before Jan 20, 2017 17:42 Mountain Time (Denver).

The Between Request Predicate

Between 路由谓词工厂接受两个参数,它们是 datetime1datetime2,它们是 java ZonedDateTime 对象。此谓词匹配在 datetime1 之后和在 datetime2 之前发生的请求。datetime2 参数必须在 datetime1 之后。以下示例配置一个 between 路由谓词:

The Between route predicate factory takes two parameters, datetime1 and datetime2 which are java ZonedDateTime objects. This predicate matches requests that happen after datetime1 and before datetime2. The datetime2 parameter must be after datetime1. The following example configures a between route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: between_route
          uri: https://example.org
          predicates:
          - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
GatewaySampleApplication.java
import java.time.ZonedDateTime;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsBetween() {
		return route("between_route")
			.route(between(ZonedDateTime.parse("2017-01-20T17:42:47.789-07:00[America/Denver]"), ZonedDateTime.parse("2017-01-21T17:42:47.789-07:00[America/Denver]")), http("https://example.org"))
			.build();
    }
}

此路由匹配 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后和在 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前发生的任何请求。这对于维护窗口可能很有用。

This route matches any request made after Jan 20, 2017 17:42 Mountain Time (Denver) and before Jan 21, 2017 17:42 Mountain Time (Denver). This could be useful for maintenance windows.

Cookie 路由谓词工厂接受两个参数,即 Cookie name 和一个 regexp(它是 java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的 Cookie。以下示例配置一个 cookie 路由谓词工厂:

The Cookie route predicate factory takes two parameters, the cookie name and a regexp (which is a Java regular expression). This predicate matches cookies that have the given name and whose values match the regular expression. The following example configures a cookie route predicate factory:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: cookie_route
          uri: https://example.org
          predicates:
          - Cookie=chocolate, ch.p
GatewaySampleApplication.java
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.between;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
		return route("cookie_route")
			.route(cookie("chocolate", "ch.p"), http("https://example.org"))
			.build();
    }
}

此路由匹配具有名为 chocolate 的 Cookie 且其值与 ch.p 正则表达式匹配的请求。

This route matches requests that have a cookie named chocolate whose value matches the ch.p regular expression.

The Header Request Predicate

Header 路由谓词工厂接受两个参数,即 header 和一个 regexp(它是 java 正则表达式)。此谓词匹配具有给定名称且其值与正则表达式匹配的标头。以下示例配置一个标头路由谓词:

The Header route predicate factory takes two parameters, the header and a regexp (which is a Java regular expression). This predicate matches with a header that has the given name whose value matches the regular expression. The following example configures a header route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: header_route
          uri: https://example.org
          predicates:
          - Header=X-Request-Id, \d+
GatewaySampleApplication.java
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.header;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCookie() {
		return route("cookie_route")
			.route(header("X-Request-Id", "\\d+"), http("https://example.org"))
			.build();
    }
}

如果请求具有名为 X-Request-Id 且其值与 \d+ 正则表达式(即它具有一个或多个数字的值)匹配的标头,则此路由匹配。

This route matches if the request has a header named X-Request-Id whose value matches the \d+ regular expression (that is, it has a value of one or more digits).

The Host Request Predicate

Host 路由谓词工厂接受一个参数:主机名 patterns 的列表。该模式是一种具有 . 作为分隔符的 Ant 样式模式。此谓词匹配与该模式匹配的 Host 标头。以下示例配置一个 host 路由谓词:

The Host route predicate factory takes one parameter: a list of host name patterns. The pattern is an Ant-style pattern with . as the separator. This predicates matches the Host header that matches the pattern. The following example configures a host route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: host_route
          uri: https://example.org
          predicates:
          - Host=**.somehost.org,**.anotherhost.org
GatewaySampleApplication.java
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.host;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsHost() {
		return route("host_route")
			.route(host("**.somehost.org", "**.anotherhost.org"), http("https://example.org"))
			.build();
    }
}

还支持 URI 模板变量(例如 {sub}.myhost.org)。

URI template variables (such as {sub}.myhost.org) are supported as well.

如果请求的 Host 标头的值为 www.somehost.orgbeta.somehost.orgwww.anotherhost.org,则此路由匹配。

This route matches if the request has a Host header with a value of www.somehost.org or beta.somehost.org or www.anotherhost.org.

此谓词将 URI 模板变量(例如前一个示例中定义的 sub)作为具有名称和值的地图提取出来,并使用 MvcUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定义的键将其置于 ServerRequest.attributes() 中。这样这些值就可以被 Gateway 处理程序筛选器函数使用了。

This predicate extracts the URI template variables (such as sub, defined in the preceding example) as a map of names and values and places it in the ServerRequest.attributes() with a key defined in MvcUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE. Those values are then available for use by Gateway Handler Filter Functions.

The Method Request Predicate

Method 请求谓词采用一个 methods 参数,该参数是一个或多个 HTTP 方法进行匹配。以下示例配置了方法路由谓词:

The Method Request Predicate takes a methods argument which is one or more parameters: the HTTP methods to match. The following example configures a method route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: method_route
          uri: https://example.org
          predicates:
          - Method=GET,POST
GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
		return route("method_route")
			.route(method(HttpMethod.GET, HttpMethod.POST), http("https://example.org"))
			.build();
    }
}

此路由在请求方法为“GET”或“POST”时匹配。

This route matches if the request method was a GET or a POST.

GatewayRequestPredicates.methodRequestPredicates.methods 的一个简单别名。此外,RouterFunctions.Builder API 包括将 methodpath RequestPredicates 相结合的便捷方法。

GatewayRequestPredicates.method is a simple alias for RequestPredicates.methods. Also, the RouterFunctions.Builder API includes convenience methods that combine the method and path RequestPredicates.

GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.methods;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsMethod() {
		return route("method_route")
			.GET("/mypath", http("https://example.org"))
			.build();
    }
}

当请求方法是 GET 且路径是 /mypath 时,此路由就会匹配成功。

This route matches if the request method was a GET and the path was /mypath.

The Path Request Predicate

Path Request Predicate 采用两个参数:Spring PathPattern patterns 的列表。此 Request Predicate 使用 RequestPredicates.path() 作为底层实现。以下示例配置路径路由谓词:

The Path Request Predicate takes two parameters: a list of Spring PathPattern patterns. This Request Predicate uses RequestPredicates.path() as the underlying implementation. The following example configures a path route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: path_route
          uri: https://example.org
          predicates:
          - Path=/red/{segment},/blue/{segment}
GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsPath() {
		return route("path_route")
			.route(path("/red/{segment}", "/blue/{segment}"), http("https://example.org"))
			.build();
    }
}

此路由在请求路径为 /red/1/red/1//red/blue/blue/green 时匹配。

This route matches if the request path was, for example: /red/1 or /red/1/ or /red/blue or /blue/green.

此谓词将 URI 模板变量(例如前一个示例中定义的 segment)作为具有名称和值的地图提取出来,并使用 RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE 中定义的键将其置于 ServerRequest.attributes() 中。这样这些值就可以被 Gateway 处理程序筛选器函数使用了。

This predicate extracts the URI template variables (such as segment, defined in the preceding example) as a map of names and values and places it in the ServerRequest.attributes() with a key defined in RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE. Those values are then available for use by Gateway Handler Filter Functions.

提供了一个实用方法(称为 get)以方便访问这些变量。以下示例展示了如何使用 get 方法:

A utility method (called get) is available to make access to these variables easier. The following example shows how to use the get method:

Map<String, Object> uriVariables = MvcUtils.getUriTemplateVariables(request);

String segment = uriVariables.get("segment");

The Query Request Predicate

Query 路由谓词工厂采用两个参数:必需的 param 和可选的 regexp(它是一个 Java 正则表达式)。以下示例配置了一个查询路由谓词:

The Query route predicate factory takes two parameters: a required param and an optional regexp (which is a Java regular expression). The following example configures a query route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: query_route
          uri: https://example.org
          predicates:
          - Query=green
GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
		return route("query_route")
			.route(query("green"), http("https://example.org"))
			.build();
    }
}

如果请求包含一个名为“green”的查询参数,则上一个路由匹配。

The preceding route matches if the request contained a green query parameter.

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: query_route
          uri: https://example.org
          predicates:
          - Query=red, gree.
GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.query;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsQuery() {
		return route("query_route")
			.route(query("red", "gree."), http("https://example.org"))
			.build();
    }
}

如果请求包含一个名为“red”的查询参数且其值匹配 gree. regexp,则上一个路由匹配,因此“green”和“greet”会匹配。

The preceding route matches if the request contained a red query parameter whose value matched the gree. regexp, so green and greet would match.

The Weight Request Predicate

Weight 路由谓词工厂采用两个参数:groupweight(一个 int)。权重是按组计算的。以下示例配置了权重路由谓词:

The Weight route predicate factory takes two arguments: group and weight (an int). The weights are calculated per group. The following example configures a weight route predicate:

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: weight_high
          uri: https://weighthigh.org
          predicates:
          - Weight=group1, 8
        - id: weight_low
          uri: https://weightlow.org
          predicates:
          - Weight=group1, 2
GatewaySampleApplication.java
import org.springframework.http.HttpMethod;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.method;

@Configuration
class RouteConfiguration {

	@Bean
	public RouterFunction<ServerResponse> gatewayRouterFunctionsWeights() {
		return route("weight_high")
				.route(weight("group1", 8).and(path("/**")), http("https://weighthigh.org"))
				.build().and(
			route("weight_low")
				.route(weight("group1", 2).and(path("/**")), http("https://weightlow.org"))
				.build());
	}
}

此路由将把约 80% 的流量转发到 [role="bare"][role="bare"]https://weighthigh.org,将约 20% 的流量转发到 [role="bare"][role="bare"]https://weightlow.org。

This route would forward ~80% of traffic to [role="bare"]https://weighthigh.org and ~20% of traffic to [role="bare"]https://weightlow.org.