114. Route 谓词工厂
Spring Cloud Gateway 将路由作为 Spring WebFlux HandlerMapping
基础架构的一部分进行匹配。 Spring Cloud Gateway 包括许多内置的 Route Predicate 工厂。所有这些谓词都与 HTTP 请求的不同属性匹配。多个路由谓词工厂可以组合,并通过逻辑and
进行组合。
114.1 Route Predicate Factory 之后
路由后谓词工厂采用一个参数,即日期时间。该谓词匹配在当前日期时间之后发生的请求。
application.yml.
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
此 Route 与 2017 年 1 月 20 日 17:42 山区时间(丹佛)之后的所有请求匹配。
114.2 Route Predicate Factory 之前
路由谓词前工厂采用一个参数,即日期时间。该谓词匹配当前日期时间之前发生的请求。
application.yml.
spring:
cloud:
gateway:
routes:
- id: before_route
uri: http://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
此 Route 与 2017 年 1 月 20 日 17:42 山区时间(丹佛)之前的所有请求匹配。
114.3 路由谓词工厂之间
路由谓词间工厂之间采用两个参数 datetime1 和 datetime2.该谓词匹配在 datetime1 之后和 datetime2 之前发生的请求。 datetime2 参数必须在 datetime1 之后。
application.yml.
spring:
cloud:
gateway:
routes:
- id: between_route
uri: http://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
此 Route 与 2017 年 1 月 20 日山区时间(丹佛)之后和 2017 年 1 月 21 日 17:42 山时间(丹佛)之后的任何请求匹配。这对于维护时段可能很有用。
114.4 CookieRoute 谓词工厂
Cookie Route Predicate Factory 采用两个参数,即 cookie 名称和正则表达式。该谓词匹配具有给定名称的 cookie,并且值匹配正则表达式。
application.yml.
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://example.org
predicates:
- Cookie=chocolate, ch.p
此路由与请求匹配,并具有一个名为chocolate
的 cookie,该 cookie 的值与ch.p
正则表达式匹配。
114.5Headers 路由谓词工厂
Headers 路由谓词工厂采用两个参数,Headers 名称和正则表达式。该谓词与具有给定名称的 Headers 匹配,并且值与正则表达式匹配。
application.yml.
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+
如果请求的标题为X-Request-Id
,而其值与\d+
正则表达式匹配(具有一个或多个数字的值),则此路由匹配。
114.6 主机路由谓词工厂
主机路由谓词工厂采用一个参数:主机名模式列表。该模式是以.
作为分隔符的 Ant 样式模式。该谓词匹配与模式匹配的Host
Headers。
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
还支持 URI 模板变量,例如{sub}.myhost.org
。
如果请求的Host
Headers 的值为www.somehost.org
或beta.somehost.org
或www.anotherhost.org
,则此路由将匹配。
该谓词提取 URI 模板变量(如上例中定义的sub
)作为名称和值的 Map,并使用ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定义的键将其放在ServerWebExchange.getAttributes()
中。这些值随后可供GatewayFilter Factories使用
114.7 方法 Route 谓词工厂
方法路由谓词工厂使用一个参数:要匹配的 HTTP 方法。
application.yml.
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://example.org
predicates:
- Method=GET
如果请求方法是GET
,则此路由将匹配。
114.8 路径路由谓词工厂
路径路由谓词工厂采用两个参数:Spring PathMatcher
模式列表和matchOptionalTrailingSeparator
的可选标志。
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Path=/foo/{segment},/bar/{segment}
如果请求路径为/foo/1
或/foo/bar
或/bar/baz
,则此路由将匹配。
该谓词提取 URI 模板变量(如上例中定义的segment
)作为名称和值的 Map,并使用ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定义的键将其放在ServerWebExchange.getAttributes()
中。这些值随后可供GatewayFilter Factories使用
可以使用 Util 方法来简化对这些变量的访问。
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
114.9 查询路由谓词工厂
查询路由谓词工厂采用两个参数:必需的param
和可选的regexp
。
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=baz
如果请求包含baz
查询参数,则此路由将匹配。
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=foo, ba.
如果请求包含一个foo
查询参数,其值与ba.
正则表达式匹配,则此路由将匹配,因此bar
和baz
将匹配。
114.10 RemoteAddr 路由谓词工厂
RemoteAddr 路由谓词工厂采用 CIDR 标记(IPv4 或 IPv6)字符串的列表(最小大小为 1),例如192.168.0.1/16
(其中192.168.0.1
是 IP 地址,16
是子网掩码)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://example.org
predicates:
- RemoteAddr=192.168.1.1/24
如果请求的远程地址为192.168.1.10
,则此路由将匹配。
114.10.1 修改解析远程地址的方式
默认情况下,RemoteAddr 路由谓词工厂使用传入请求中的远程地址。如果 Spring Cloud Gateway 位于代理层后面,则此地址可能与实际的 Client 端 IP 地址不匹配。
您可以通过设置自定义RemoteAddressResolver
来定制解析远程地址的方式。 Spring Cloud Gateway 随附了一个基于X-Forwarded-For header,XForwardedRemoteAddressResolver
的非默认远程地址解析器。
XForwardedRemoteAddressResolver
有两种静态构造方法,它们采用不同的安全性方法:
XForwardedRemoteAddressResolver::trustAll
返回一个RemoteAddressResolver
,该RemoteAddressResolver
始终采用X-Forwarded-For
Headers 中找到的第一个 IP 地址。这种方法容易受到欺骗的攻击,因为恶意 Client 端可能会为X-Forwarded-For
设置初始值,解析器会接受该初始值。
XForwardedRemoteAddressResolver::maxTrustedIndex
取得一个索引,该索引与 Spring Cloud Gateway 前面运行的受信任基础结构的数量相关。例如,如果只能通过 HAProxy 访问 Spring Cloud Gateway,则应使用值 1.如果在访问 Spring Cloud Gateway 之前需要两跳可信基础架构,则应使用值 2.
给定以下 Headers 值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
下面的maxTrustedIndex
值将产生以下远程地址。
maxTrustedIndex | result |
---|---|
[ Integer.MIN_VALUE ,0] | (无效,初始化期间为IllegalArgumentException ) |
1 | 0.0.0.3 |
2 | 0.0.0.2 |
3 | 0.0.0.1 |
[4, Integer.MAX_VALUE ] | 0.0.0.1 |
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")
)