[spring cloud gateway]yml中Route Predicate的配置

前言

 

本章节将介绍yml中 predicate中都可以配置哪些内容

下面所有的例子中,最终都要通过gateway路由到(跳转到)下面这个服务的ping接口

The After Route Predicate Factory

意思就是在predicate中配置一个叫做after的参数,直接先上图,然后讲解

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - After=2017-01-20T17:42:47.789-07:00[America/Denver]
        filters: 
          - StripPrefix=1
#StripPrefix会将url如/api/order/ping中的/api去掉后跟-path的值匹配,如果不想去掉/api就把这个去掉就行

 作用:只有你当前发起的请求的时间在这个after属性设置的时间之后,才能将请求路由到uri设置的地址上。看下面例子:

我当前gateway服务的实在localhost:9001上,gateway配置如下

我要请求的内容实在localhost:8001上,如下:

假设我当前发送请求的时间是2022-07-07 14:45,根据上面的配置,我当前的时间实在after设置的之后,是满足这个设置的,所以当我起如下请求时localhost:9001/api/order/ping时,gateway会拦截到这个请求,然后检查他的请求时间满足我们after的设置,然后就会把这个请求路由到(转发到)localhost:8001/order/ping(为什么会变成这个url参考前面内容,不是这章的内容),然后就会得到一个pong的值。

但是如果我们现在把after属性的时间改成2024年(当前时间时2022年)如下:

当前发送请求的时间时2016年,那么他就不满足after设置,这是gateway就会报错,如下:

 

 这就是after的作用。

The before Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
        filters: 
          - StripPrefix=1
 

before与after作用相同,只不过判断的条件不同,after是请求时间在after设置的时间之后就true,而before是请求的时间在before设置的时间之前才为true。例子我就不写了,参考after就行

The Between Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
 

作用:只有当前请求的时间在between设置的时间之间时,表示才会路由(转发)到uri对应的地址上。具体根after和before相同,就不再举例

The Cookie Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Cookie=chocolate, ch.p

作用:只有当前请求中中含有一个name为chocolate,他的值为ch.p的cookie时,表示才会路由(转发)到uri对应的地址上。

例子:

 因为请求中设置了cookie,与yml中设置的对应,所以请求成功了,否则请求失败。

The Headers Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Header=X-Request-Id, \d+ 
#Hearder中必须包含一个X-Request-Id的字段,他的值必须满足这个正则表达式

作用:只有当前请求中中含有一个名为X-Request-Id,他的值为数字开头header时,表示才会路由(转发)到uri对应的地址上。

看例子:

 当header中含有X-Requet-Id,并且其值为数字时(满足了yml中正则表达式),就可以成功请求。否则报错404。

The host Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Host=**.somehost.org,**.anotherhost.org
#header中的host的值必须满足这个正则表达式

作用:只有当前请求的header中包含一个host属性时,并且host的值满足上面的设置时,才会路由(转发)到uri对应的地址上。

例子:

 虽然我的请求的地址时localhost,但是只要我的header中的host属性满足yml中host的规则就可以请求成功,否则会报404错误。

The Method Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Method=GET,POST #只有当前时get或者post请求才行

作用:请求有四种方法get,post,put,delete,只有当前请求你用的方法与yml中-Method设置的相匹配时,才会路由(转发)到uri对应的地址上。

例子:

 当使用的方法与yml中的Method的配置(get,post)不匹配时,请求就失败了。只有请求时我把红框里改为get或者post请求才会成功

The Path Route Predicate Factory

这个是最常用的一个,先看配置

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Path=/api/order/** #请求地址出去ip:端口后其他部分与这个匹配才行

作用:当请求除去ip地址:端口这部分后,剩余的部分(也成为path部分)与我们yml设置的Path匹配时,才会路由(转发)到uri对应的地址上。

例子:

 我的请求中path部分与yml中path的设置匹配,所以请求就会成功访问

另外i,我们还可以这样写:

predicates:
        - Path=/red/{segment},/blue/{segment}

这个{segment}表示一种路径变量,比如当你的请求path时/red/1,或者/red/a时,那么我们在GatewayFilter类中就可以通过代码获取到这个1,和a,如下:

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

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

The Query Route Predicate Factory

所谓Query指的就是我们请求中的请求参数。先看yml

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - Query=id  #值也可以写多个,用逗号隔开,另外这个值还可以使用正则表达式

作用:我们的请求中必须带有query指定的内容,请求才能匹配成功,才会路由(转发)到uri对应的地址上。

例子:

 一定要注意:-Query=value1,value2,这样配置时是一个并列关系,也就是请求中必须同时含有这个两个参数才行。

The RemoteAddress Route Predicate Factory

意思指定客户端也就是发起请求的电脑的ip地址必须是我yml中配置的ip才行

spring:
  cloud:
    gateway:
      routes:
      - id: order-route
        uri: http://localhost:8001
        predicates:
          - RemoteAddr=192.168.1.104 #还可以使用192.168.1.104/24的形式,24是掩码位数

作用:发起请求的电脑的ip地址必须是-RemoteAddr指定的,请求才能匹配成功,才会路由(转发)到uri对应的地址上。

例子:

 我的局域网ip是192.168.1.104,与yml配置匹配,所以就成功了。
注意:请求时不能用localhost或者127.0.0.1,这样都是无效的,这样会导致服务端判断来源的时候取得的网卡地址为0.0.0.0。一定要写自己的ip地址

The Weight Route Predicate Factory

意思就是通过权重的方式指定路由到uri的比例。使用weight时,它要包含2个参数,一个是group,一个是weight的值,如下配置中group1就是参数1的group,8和2就是参数2的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

比如这个配置,就是说10次请求的话,8次将请求到https//weighthigh.org这个uri中的接口,2次将请求到https//weightlow.org这个uri中的接口.因为本人就一台机器,就不做例子了。

Modifying the Way Remote Addresses Are Resolved

一般来说我们都直接接受客户端发来的请求,但是有的时候,我们会在gateway服务前面加上一个类似于nginx这样的代理服务器,这是如果我们在yml中使用-RemoteAddr来配置时就有问题了。因为这是请求进来的所有地址都似乎代理服务器的地址,不是客户端(真正发请求的人)的地址,所以就用到这里方案RemoteAddressResolver,其原理就是通过解析请求的header中的 X-Forwarded-For,如果不懂这个名字,可以去百度。

这里说一下请求中的header中写X-Forwarded-For的格式:

X-Forwarded-For 请求头格式非常简单,就这样:

X-Forwarded-For: client, proxy1, proxy2

可以看到,XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。

如果一个 HTTP 请求到达服务器之前,经过了三个代理 Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0,那么按照 XFF 标准,服务端最终会收到以下信息:

X-Forwarded-For: IP0, IP1, IP2

例子 :这个的配置较为麻烦,仔细看

首先因为要使用RemoteAddressResolver(这是个接口),我们要先把他的实现类放到容器中,所以先做一下配置:

//这段代码放到启动类中也行,过着自己放在一个有@Configuration注解的类中也行 
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(3);
//这个ip就好比在yml中-RemoteAddr设置的ip作用一样【1】
private static final String [] remoteAddr={ "192.168.1.104"};
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
       return builder.routes().route("order_route",
               r -> r.path("/api/order/ping")
                       .and().remoteAddr(resolver,remoteAddr)
                       .filters(f-> f.stripPrefix(1))
                       .uri("http://localhost:8001"))
               .build();
}

要使用RemoteAddresszReslover的话就要使用代码方式,不能通过yml方式,所以这里配置router的就不要在yml配置了,其他的router可以在yml中配置,最后会合并二者。

然后,我们通过postman发起请求如下:

 我们看到请求成功了。

下面我说一下过程:
XForwardedRemoteAddressResolver会解析postman中

 然后会把这三个值的顺序进行一个反转放在一个数组为[0.0.0.3,0.0.0.2,192.168.1.104],

然后我们maxTrustedIndex(3)实际会指向数组的第三个值也就是192.168.1.104,然后拿着这个值根变量remoteAddr的值比较,如果相同说明匹配成功,就可以转发到localhost:8001/order/ping,就请求成功了。


 

关于这个以下几个点需要明白:
1.在header中X-Forwardared-For的书写规则(上面写了)。
2.代码中api的maxTrustedIndex(index)这个index是对应的X-Forwarded-For右侧的第几个(从1开始),至于原因在上面原理说过。

官网中的图就是上面那段原理的意思

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值