跳到主要内容
版本:5.0.1

路由断言工厂

DeepSeek V3 中英对照 Route Predicate Factories

Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础设施的一部分。Spring Cloud Gateway 包含许多内置的路由断言工厂。所有这些断言都匹配 HTTP 请求的不同属性。您可以通过逻辑 and 语句组合多个路由断言工厂。

After 路由断言工厂​

After 路由谓词工厂接受一个参数 datetime(这是一个 Java ZonedDateTime)。此谓词匹配发生在指定日期时间之后的请求。以下示例配置了一个 after 路由谓词:

spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]

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

Before 路由断言工厂​

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

spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

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

Between 路由断言工厂​

Between 路由断言工厂接收两个参数:datetime1 和 datetime2,它们都是 Java ZonedDateTime 对象。该断言匹配发生在 datetime1 之后且 datetime2 之前的请求。datetime2 参数必须在 datetime1 之后。以下示例配置了一个 between 路由断言:

spring:
cloud:
gateway:
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]

该路由匹配在 2017 年 1 月 20 日 17:42 山地时间(丹佛)之后,且在 2017 年 1 月 21 日 17:42 山地时间(丹佛)之前发出的任何请求。这对于维护窗口非常有用。

Cookie 路由谓词工厂接受两个参数:cookie name 和 regexp(这是一个 Java 正则表达式)。该谓词匹配具有给定名称且其值符合正则表达式的 cookie。以下示例配置了一个 cookie 路由谓词工厂:

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p

该路由匹配包含名为 chocolate 的 cookie 且其值符合 ch.p 正则表达式的请求。

Header 路由断言工厂​

Header 路由谓词工厂接收两个参数:header 和 regexp(这是一个 Java 正则表达式)。该谓词会匹配具有指定名称且其值符合正则表达式的请求头。以下示例配置了一个基于请求头的路由谓词:

spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+

该路由匹配的条件是:请求包含名为 X-RequestId 的请求头,且其值符合 \d+ 正则表达式(即该值由一个或多个数字组成)。

主机路由断言工厂​

Host 路由谓词工厂接收一个参数:主机名 patterns 列表。该模式是以 . 作为分隔符的 Ant 风格模式。此谓词会匹配与模式相符的 Host 头部。以下示例配置了一个主机路由谓词:

spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org

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

该路由匹配的条件是请求的 Host 头部值为 www.somehost.org、beta.somehost.org 或 www.anotherhost.org。

该谓词将 URI 模板变量(例如前面示例中定义的 sub)提取为名称和值的映射,并将其放入 ServerWebExchange.getAttributes() 中,键由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。然后,这些值可供 GatewayFilter 工厂 使用。

方法路由断言工厂​

Method 路由谓词工厂接受一个 methods 参数,该参数可以是一个或多个 HTTP 方法,用于匹配请求。以下示例配置了一个方法路由谓词:

spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST

如果请求方法是 GET 或 POST,则此路由匹配。

路径路由断言工厂​

Path 路由断言工厂接收两个参数:一个 Spring PathMatcher patterns 列表和一个名为 matchTrailingSlash 的可选标志(默认为 true)。以下示例配置了一个路径路由断言:

spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}

该路由匹配的请求路径示例包括:/red/1、/red/1/、/red/blue 或 /blue/green。

如果 matchTrailingSlash 设置为 false,那么请求路径 /red/1/ 将不会被匹配。

如果你设置了 spring.webflux.base-path 属性,这将会影响路径匹配。该属性的值会自动添加到路径模式之前。例如,当 spring.webflux.base-path=/app 且路径模式为 /red/{segment} 时,用于匹配的完整模式将是 /app/red/{segment}。

该谓词将 URI 模板变量(例如前面示例中定义的 segment)提取为名称和值的映射,并将其放入 ServerWebExchange.getAttributes() 中,键值由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。然后这些值可供 GatewayFilter 工厂 使用。

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

Map<String, String> uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);

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

查询路由谓词工厂​

Query 路由断言工厂接收两个参数:必需的 param 和可选的 regexp(这是一个 Java 正则表达式)。以下示例配置了一个查询路由断言:

spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green

如果请求中包含 green 查询参数,则前面的路由匹配。

spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.

如果请求中包含一个值为 red 的查询参数,并且该值匹配正则表达式 gree.,那么前面的路由就会匹配,因此 green 和 greet 都会匹配。

远程地址路由断言工厂​

RemoteAddr 路由谓词工厂接收一个 sources 列表(最小长度为 1),这些源是 CIDR 表示法(IPv4 或 IPv6)字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。以下示例配置了一个 RemoteAddr 路由谓词:

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24

如果请求的远程地址为 192.168.1.10,则此路由匹配。

修改远程地址解析方式​

默认情况下,RemoteAddr 路由谓词工厂使用传入请求的远程地址。如果 Spring Cloud Gateway 位于代理层之后,这可能与实际客户端 IP 地址不匹配。

您可以通过设置自定义的 RemoteAddressResolver 来定制远程地址的解析方式。Spring Cloud Gateway 附带了一个非默认的远程地址解析器,它基于 X-Forwarded-For 标头,即 XForwardedRemoteAddressResolver。

XForwardedRemoteAddressResolver 有两个静态构造方法,它们采用不同的安全方法:

  • XForwardedRemoteAddressResolver::trustAll 返回一个始终采用 X-Forwarded-For 头部中找到的第一个 IP 地址的 RemoteAddressResolver。这种方法容易受到欺骗,因为恶意客户端可以为 X-Forwarded-For 设置一个初始值,而解析器会接受该值。

  • XForwardedRemoteAddressResolver::maxTrustedIndex 接受一个索引,该索引对应于在 Spring Cloud Gateway 前方运行的受信任基础设施的数量。例如,如果 Spring Cloud Gateway 只能通过 HAProxy 访问,则应使用值 1。如果在访问 Spring Cloud Gateway 之前需要经过两层受信任的基础设施,则应使用值 2。

考虑以下标头值:

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

以下 maxTrustedIndex 值对应以下远程地址:

maxTrustedIndex结果
[Integer.MIN_VALUE,0](无效,初始化期间抛出 IllegalArgumentException)
10.0.0.3
20.0.0.2
30.0.0.1
[4, Integer.MAX_VALUE]0.0.0.1

以下示例展示了如何使用 Java 实现相同的配置:

RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);

...

.route("direct-route",
r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
.uri("https://downstream1")
.route("proxied-route",
r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
.uri("https://downstream2")
)

权重路由断言工厂​

Weight 路由谓词工厂接受两个参数:group 和 weight(一个整数)。权重是按组计算的。以下示例配置了一个权重路由谓词:

spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2

此路由会将约 80% 的流量转发至 weighthigh.org,约 20% 的流量转发至 weightlow.org

XForwarded Remote Addr 路由断言工厂​

XForwarded Remote Addr 路由谓词工厂接收一个 sources 列表(最小长度为 1),这些 sources 是 CIDR 表示法(IPv4 或 IPv6)的字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

该路由谓词允许根据 X-Forwarded-For HTTP 头来过滤请求。

这可以与反向代理(如负载均衡器或Web应用防火墙)结合使用,在这些场景中,只有当请求来自这些反向代理使用的受信任IP地址列表时,才应允许该请求。

以下示例配置了一个 XForwardedRemoteAddr 路由谓词:

spring:
cloud:
gateway:
routes:
- id: xforwarded_remoteaddr_route
uri: https://example.org
predicates:
- XForwardedRemoteAddr=192.168.1.1/24

当 X-Forwarded-For 头部包含例如 192.168.1.10 时,此路由将匹配。