5. 路由谓词工厂
Spring Cloud Gateway 将路由匹配为 Spring WebFlux 的一部分HandlerMapping
基础设施。
Spring Cloud Gateway 包括许多内置的路由谓词工厂。
所有这些谓词都匹配 HTTP 请求的不同属性。
您可以将多个路由谓词工厂与逻辑and
语句。
5.1. After 路由谓词工厂
这After
route 谓词工厂接受一个参数,一个datetime
(这是一个 javaZonedDateTime
).
此谓词匹配在指定日期时间之后发生的请求。
以下示例配置 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 山区时间(丹佛)之后提出的任何请求相匹配。
5.2. Before Route谓词工厂
这Before
route 谓词工厂接受一个参数,一个datetime
(这是一个 javaZonedDateTime
).
此谓词匹配在指定datetime
.
以下示例配置了 before route 谓词:
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(丹佛)之前提出的任何请求。
5.3. Between 路由谓词工厂
这Between
route 谓词工厂采用两个参数,datetime1
和datetime2
哪些是 JavaZonedDateTime
对象。
此谓词匹配在datetime1
和之前datetime2
.
这datetime2
参数必须在datetime1
.
以下示例配置了 between route 谓词:
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 山区时间(丹佛)之前提出的任何请求相匹配。 这对于维护时段可能很有用。
5.4. Cookie 路由谓词工厂
这Cookie
route 谓词工厂采用两个参数,即 cookiename
和regexp
(这是一个 Java 正则表达式)。
此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。
以下示例配置 cookie 路由谓词工厂:
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
此路由匹配具有名为chocolate
其值与ch.p
正则表达式。
5.5. 标头路由谓词工厂
这Header
route 谓词工厂采用两个参数,即header
和regexp
(这是一个 Java 正则表达式)。
此谓词与具有给定名称的标头匹配,其值与正则表达式匹配。
以下示例配置标头路由谓词:
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
如果请求具有名为X-Request-Id
其值与\d+
正则表达式(即,它的值为一个或多个数字)。
5.6. 主机路由谓词工厂
这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
工厂
5.7. 方法路由谓词工厂
这Method
路由谓词工厂采用methods
参数,这是一个或多个参数:要匹配的 HTTP 方法。
以下示例配置方法路由谓词:
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
如果请求方法是GET
或POST
.
5.8. 路径路由谓词工厂
这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/
将不匹配。
此谓词提取 URI 模板变量(例如segment
,在前面的示例中定义)作为名称和值的映射,并将其放置在ServerWebExchange.getAttributes()
在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
.
然后,这些值可供GatewayFilter
工厂
实用程序方法(称为get
) 可以更轻松地访问这些变量。
以下示例演示如何使用get
方法:
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
5.9. 查询路由谓词工厂
这Query
路由谓词工厂采用两个参数:必需的param
和可选的regexp
(这是一个 Java 正则表达式)。
以下示例配置查询路由谓词:
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
如果请求包含green
query 参数。
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.
如果请求包含red
query 参数,其值与gree.
正则表达式,所以green
和greet
会匹配。
5.10. RemoteAddr路由谓词工厂
这RemoteAddr
路由谓词工厂采用列表(最小大小 1)sources
,它们是 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
.
5.11. 权重路由谓词工厂
这Weight
route 谓词工厂接受两个参数: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% 的流量转发到 weighlow.org
5.11.1. 修改远程地址的解析方式
默认情况下,RemoteAddr 路由谓词工厂使用传入请求中的远程地址。如果 Spring Cloud Gateway 位于代理层后面,则这可能与实际的客户端 IP 地址不匹配。
您可以通过设置自定义RemoteAddressResolver
.
Spring Cloud Gateway 附带一个基于 X-Forwarded-For 标头的非默认远程地址解析器,XForwardedRemoteAddressResolver
.
XForwardedRemoteAddressResolver
有两个静态构造函数方法,它们采用不同的安全方法:
-
XForwardedRemoteAddressResolver::trustAll
返回一个RemoteAddressResolver
始终采用在X-Forwarded-For
页眉。 此方法容易受到欺骗,因为恶意客户端可能会为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 |
结果 |
---|---|
[ |
(无效, |
1 |
0.0.0.3 |
2 |
0.0.0.2 |
3 |
0.0.0.1 |
[4, |
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")
)