5. 路由断言工厂

Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础设施的一部分进行处理。
Spring Cloud Gateway 包含许多内置的路由谓词工厂。
所有这些谓词均基于 HTTP 请求的不同属性进行匹配。
您可以使用逻辑 and 语句组合多个路由谓词工厂。spring-doc.cadn.net.cn

5.1. 后置路由谓词工厂

路由谓词工厂 After 接受一个参数,即 datetime(这是一个 Java ZonedDateTime)。该谓词匹配在指定时间之后发生的请求。以下示例配置了一个 'after' 路由谓词:spring-doc.cadn.net.cn

示例 1. application.yml
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山地时间(丹佛)之后发出的任何请求。spring-doc.cadn.net.cn

5.2. 前置路由谓词工厂

路由谓词工厂 Before 接受一个参数,即一个 datetime(这是一个 Java ZonedDateTime)。该谓词匹配在指定的 datetime 之前发生的请求。以下示例配置了一个 'before' 路由谓词:spring-doc.cadn.net.cn

示例 2. application.yml
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山地时间(丹佛)之前的任何请求。spring-doc.cadn.net.cn

5.3. Between 路由谓词工厂

路由谓词工厂 Between 接受两个参数,datetime1datetime2,它们是 Java ZonedDateTime 对象。此谓词匹配发生在 datetime1 之后且在 datetime2 之前的请求。参数 datetime2 必须位于 datetime1 之后。以下示例配置了一个 between 路由谓词:spring-doc.cadn.net.cn

示例 3. application.yml
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(山地时间,丹佛)之前的任何请求。<br/>这在维护窗口期间可能很有用。spring-doc.cadn.net.cn

路由谓词工厂 Cookie 接受两个参数:cookie 名称 name 和一个 regexp(即 Java 正则表达式)。该谓词用于匹配具有指定名称且其值与正则表达式相匹配的 cookie。以下示例配置了 cookie 路由谓词工厂:spring-doc.cadn.net.cn

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

此路由匹配具有名为 chocolate 的 Cookie,且其值与 ch.p 正则表达式相匹配的请求。spring-doc.cadn.net.cn

5.5. 头部路由谓词工厂

路由谓词工厂 Header 接受两个参数,即 headerregexp(其中 regexp 是一个 Java 正则表达式)。该谓词会匹配具有指定名称的头部,且其值与正则表达式相匹配。以下示例配置了一个基于头部的路由谓词:spring-doc.cadn.net.cn

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

此路由匹配的条件是:请求包含一个名为 X-Request-Id 的头信息,且其值满足 \d+ 所指定的正则表达式(即该值由一个或多个数字组成)。spring-doc.cadn.net.cn

5.6. 主机路由谓词工厂

路由谓词工厂 Host 接受一个参数:主机名列表 patterns。模式为 Ant 风格模式,其中 . 作为分隔符。此谓词匹配符合该模式的 Host 头部。以下示例配置了主机路由谓词:spring-doc.cadn.net.cn

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

URI 模板变量(例如 {sub}.myhost.org)也受支持。spring-doc.cadn.net.cn

此路由匹配的条件是请求包含 Host 头部,且其值为 www.somehost.orgbeta.somehost.orgwww.anotherhost.orgspring-doc.cadn.net.cn

此谓词会提取 URI 模板变量(例如前例中定义的 sub)并将其作为名称与值的映射放入 ServerWebExchange.getAttributes() 中,键由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。随后,这些值即可供 GatewayFilter 工厂 使用。spring-doc.cadn.net.cn

5.7. 方法路由谓词工厂

路由谓词工厂 Method 接受一个 methods 参数,该参数可包含一个或多个参数:用于匹配的 HTTP 方法。
以下示例配置了一个方法路由谓词:spring-doc.cadn.net.cn

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

此路由匹配的条件是请求方法为 GETPOSTspring-doc.cadn.net.cn

5.8. 路径路由断言工厂

路由谓词工厂(Path Route Predicate Factory)接受两个参数:一个 Spring PathMatcher patterns 列表,以及一个可选的标志位 matchTrailingSlash(默认值为 true)。
以下示例配置了一个路径路由谓词:spring-doc.cadn.net.cn

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

此路由匹配请求路径为以下示例之一的情况:/red/1/red/1//red/blue/blue/greenspring-doc.cadn.net.cn

如果将 matchTrailingSlash 设置为 false,则请求路径 /red/1/ 将不会被匹配。spring-doc.cadn.net.cn

此谓词会提取 URI 模板变量(例如前例中定义的 segment)并将其作为名称与值的映射放入 ServerWebExchange.getAttributes() 中,键由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。随后,这些值即可供 GatewayFilter 工厂 使用。spring-doc.cadn.net.cn

一个实用方法(称为get)可以更方便地访问这些变量。 以下示例展示了如何使用get方法:spring-doc.cadn.net.cn

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

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

5.9 查询参数路​由断言工厂

Query 路由谓词工厂需要两个参数:一个必填的param和一个可选的regexp(这是一个Java正则表达式)。下面的例子配置了一个查询路由谓词:spring-doc.cadn.net.cn

(此处填写自动生成的翻译结果)
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green

前面的路线如果请求包含一个< code> 0 查询参数。spring-doc.cadn.net.cn

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

前一个路由匹配如果请求包含一个查询参数为0其值匹配正则表达式1,所以2和3将匹配。spring-doc.cadn.net.cn

5.10. 远程地址路由谓词工厂

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

例子 10。application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

此路线匹配远程请求地址,例如192.168.1.10spring-doc.cadn.net.cn

5.11. 重量度量路线断言工厂

Weight 路由谓词工厂需要两个参数: groupweight(一个整数)。按组计算权重。 在下面的示例中,配置了加权路由谓词:spring-doc.cadn.net.cn

示例11. application.yml
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%的流量转发到 weighlow.orgspring-doc.cadn.net.cn

5.11.1. 修改远程地址解析方式

默认情况下,RemoteAddr 路由谓词工厂使用来自传入请求的远程地址。如果 Spring Cloud Gateway 后面有一层代理,则这可能与实际客户端 IP 地址不匹配。spring-doc.cadn.net.cn

您可以设置自定义RemoteAddressResolver来定制远程地址的解析方式。Spring Cloud Gateway随附一个基于X-Forwarded-For标头的非默认远程地址解析器,XForwardedRemoteAddressResolverspring-doc.cadn.net.cn

XForwardedRemoteAddressResolver 有两个静态构造方法,它们采用不同的安全方法:spring-doc.cadn.net.cn

  • XForwardedRemoteAddressResolver::trustAll 会返回一个值RemoteAddressResolver,该值始终采用X-Forwarded-For标头中找到的第一个 IP 地址。此方法容易受到伪造攻击,因为恶意客户可以为X-Forwarded-For设置初始值,而解析器将接受该值。spring-doc.cadn.net.cn

  • XForwardedRemoteAddressResolver::maxTrustedIndex 是与前面运行的受信任基础设施的数量相关的索引。 如果只有通过 HAProxy 可访问 Spring Cloud Gateway,则应使用值 1。 如果在可访问 Spring Cloud Gateway 之前需要两个跳数的信任基础设施,那么应该使用值 2。spring-doc.cadn.net.cn

考虑以下标题值:spring-doc.cadn.net.cn

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

以下值为 0,则产生以下远程地址:spring-doc.cadn.net.cn

maxTrustedIndex 结果

[Integer.MIN_VALUE,0]spring-doc.cadn.net.cn

(初始化期间出错,代码为IllegalArgumentException)spring-doc.cadn.net.cn

1spring-doc.cadn.net.cn

0.0.0.3spring-doc.cadn.net.cn

2spring-doc.cadn.net.cn

0.0.0.2spring-doc.cadn.net.cn

3spring-doc.cadn.net.cn

0.0.0.1spring-doc.cadn.net.cn

[4, Integer.MAX_VALUE]spring-doc.cadn.net.cn

0.0.0.1spring-doc.cadn.net.cn

下面的示例展示了如何使用Java实现相同的配置:spring-doc.cadn.net.cn

示例12. GatewayConfig.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")
)