一 何为路由谓词工厂(Route Predicate Factories)
Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。 Spring Cloud Gateway包括许多内置的路由谓词工厂。所有这些谓词都与HTTP请求的不同属性匹配。可以将多个路由谓词工厂与逻辑和语句结合使用。
二 框架自带了哪些路由谓词工厂
AfterRoutePredicateFactoryAfterRoutePredicateFactory接收一个参数,即datetime(这是一个JavaZonedDateTime)。该谓词匹配在指定日期时间之后发生的请求。如以下示例配置:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]BeforeRoutePredicateFactoryBeforeRoutePredicateFactory接收一个参数,即datetime(这是一个JavaZonedDateTime)。该谓词匹配在指定日期时间之前发生的请求。如以下示例配置:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]BetweenRoutePredicateFactoryBetweenRoutePredicateFactory接收两个参数datetime1和datetime2,它们是javaZonedDateTime对象。该谓词匹配在datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。如以下示例配置:1
2
3
4
5
6
7
8spring:
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]CookieRoutePredicateFactoryCookieRoutePredicateFactory接收两个参数,即cookiename和一个regexp(这是Java正则表达式)。该谓词匹配具有给定名称且其值与正则表达式匹配的cookie。以下示例配置Cookie路由谓词工厂:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.pHeaderRoutePredicateFactoryHeaderRoutePredicateFactory接收两个参数,请求头的name和一个regexp(这是Java正则表达式)。该谓词与具有给定名称的请求头匹配,该请求头的值与正则表达式匹配。以下示例配置标头路由谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+HostRoutePredicateFactoryHostRoutePredicateFactory接收一个参数,即主机名列表patterns,该patterns是带有的Ant样式的模式。作为分隔符。该谓词与匹配模式的Host请求头匹配。以下示例配置主机路由谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org还支持URI模板变量(例如
{sub} .myhost.org),以上示例如果请求的主机请求头的值为www.somehost.org或beta.somehost.org或www.anotherhost.org,则此路由匹配。他的谓词提取URI模板变量(如上例中定义的sub)作为名称和值的映射,并使用
ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义的键将其放置在ServerWebExchange.getAttributes()中。这些值可供GatewayFilter工厂使用。MethodRoutePredicateFactoryMethodRoutePredicateFactory接收methods参数,该参数是一个或多个参数:要匹配的HTTP方法。以下示例配置方法route谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST此示例,如果请求方法是GET或POST,则此路由匹配。
PathRoutePredicateFactoryPathRoutePredicateFactory是路径路由谓词工厂,在实际生产中是用的最多的,接收两个参数:SpringPathMatcherpatterns列表和一个称为matchOptionalTrailingSeparator的可选标志。以下示例配置路径路由谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}该谓词提取URI模板变量(如上例中定义的
segment)作为名称和值的映射,并使用ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE中定义的键将其放置在ServerWebExchange.getAttributes()中。这些值可供GatewayFilter工厂使用。访问该变量的方式如下1
2Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");QueryRoutePredicateFactoryQueryRoutePredicateFactory是根据查询参数匹配的路由谓词工厂,接收两个参数:必需的param和可选的regexp(这是Java正则表达式)。以下示例配置查询路由谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green如果请求包含
green查询参数,则前面的路由匹配。1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.如上示例,如果查询参数包含
red,并且其值与gree.正则匹配,如green和greet都会被匹配。RemoteAddrRoutePredicateFactoryRemoteAddrRoutePredicateFactory接收一个参数sources列表(最小大小为1),这些sources是CIDR标记(IPv4或IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是IP地址,而16是子网掩码) )。下面的示例配置RemoteAddr路由谓词:1
2
3
4
5
6
7
8spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24如果请求的远程地址是例如192.168.1.10,则此路由匹配。
WeightRoutePredicateFactoryWeightRoutePredicateFactory是权重路由谓词工厂,接收两个参数:group和weight(一个int)。权重是按组计算的。以下示例配置权重路由谓词:1
2
3
4
5
6
7
8
9
10
11
12spring:
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。
默认情况下,RemoteAddr路由谓词工厂使用传入请求中的远程地址。如果Spring Cloud Gateway位于代理层后面,则此地址可能与实际的客户端IP地址不匹配。
您可以通过设置自定义的
RemoteAddressResolver来自定义解析远程地址的方式。 Spring Cloud Gateway随附了一个基于X-Forwarded-For标头XForwardedRemoteAddressResolver的非默认远程地址解析器。XForwardedRemoteAddressResolver有两个静态构造函数方法,它们采用不同的安全性方法:XForwardedRemoteAddressResolver::trustAll返回一个RemoteAddressResolver,该地址始终采用X-Forwarded-For请求头中找到的第一个IP地址。这种方法容易受到欺骗的攻击,因为恶意客户端可能会为X-Forwarded-For设置初始值,该初始值将被解析器接受。XForwardedRemoteAddressResolver::maxTrustedIndex获取一个索引,该索引与在Spring Cloud Gateway前面运行的受信任基础结构的数量相关。例如,如果只能通过HAProxy访问Spring Cloud Gateway,则应使用值1。如果在访问Spring Cloud Gateway之前需要两跳可信基础架构,则应使用值2。
Forwarded了多次的,如以下请求头,和
maxTrustedIndex对应关系1
2> X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
>
maxTrustedIndex | result |
|---|---|
[Integer.MIN_VALUE,0] | (invalid, IllegalArgumentException during initialization) |
| 1 | 0.0.0.3 |
| 2 | 0.0.0.2 |
| 3 | 0.0.0.1 |
[4, Integer.MAX_VALUE] | 0.0.0.1 |
三 自定义路由谓词工厂
路由谓词工厂的定义与路由过滤器的定义非常相似,我们只需要继承
AbstractRoutePredicateFactory<Config>,并重写里面的方法apply方法即可。apply方法重写如下:
1 |
|
定义快捷方式配置写法的字段顺序,重写以下方法:
1 |
|
其中的
Config一般是自定义过滤器工厂的静态内部类,主要是定义传递的参数,如
1 | public static class Config { |
一个示例如下:
1 | public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> { |
