访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等; 本篇概览 作为《Spring Cloud Gateway实战》系。..

                                                                                                                                                                                    ##### 欢迎访问我的GitHub 

https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

本篇概览
1
作为《Spring Cloud Gateway实战》系列的第五篇,是时候了解过滤器(filter)的作用了,本篇咱们一起来了解Spring Cloud Gateway内置好的过滤器,真是种类繁多功能强大 
AddRequestHeader

AddRequestHeader过滤器顾名思义,就是在请求头部添加指定的内容
带有predicate的完整配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  server:
#服务端口
port: 8081
spring:
application:
name: hello-gateway
cloud:
gateway:
routes:
- id: path_route
uri: http://127.0.0.1:8082
predicates:
- Path=/hello/
filters:
- AddRequestHeader=x-request-foo, bar-config

`带有predicate的完整动态配置:```json
[
{
"id": "path_route_addr",
"uri": "http://127.0.0.1:8082",
"predicates": [
{
"name": "Path",
"args": {
"pattern": "/hello/"
}
],
"filters": [
{
"name": "AddRequestHeader",
"name": "x-request-foo",
"value": "bar-dynamic"
}
]
}
]

实际效果:

AddRequestParameter

AddRequestParameter过滤器顾名思义,就是添加请求参数
配置如下,服务提供方收到的请求中会多一个参数,名为foo,值为bar-config:

#服务端口

1
- AddRequestParameter=foo, bar-config

[
{
{
}
],
{
“name”: “AddRequestParameter”,
“name”: “foo”,
}
]
}
]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  

实际效果:


##### AddResponseHeader

AddResponseHeader过滤器就是在响应的header中添加参数
配置如下,客户端收到的响应,其header中会多一个参数,名为foo,值为bar-config-response:


#服务端口
- AddResponseHeader=foo, bar-config-response

[
{
{
}
],
{
"name": "AddResponseHeader",
"value": "bar-dynamic-response"
}
]
}
]

实际效果:

DedupeResponseHeader
1
服务提供方返回的response的header中,如果有的key出线了多个value(例如跨域场景下的Access-Control-Allow-Origin),DedupeResponseHeader过滤器可以将重复的value剔除调,剔除策略有三种:RETAIN_FIRST (保留第一个,默认), RETAIN_LAST(保留最后一个), RETAIN_UNIQUE(去重)  

配置如下,指定了两个header key的去重,策略是保留最后一个:

#服务端口

1
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_LAST
1
2
3
4
5
6




#服务端口

CircuitBreaker

CircuitBreaker即断路器,咱们在单独的一篇中深入体验这个强大的功能吧

FallbackHeaders

FallbackHeaders一般和CircuitBreaker配合使用,来看下面的配置,发生断路后,请求会被转发FallbackHeaders去处理,此时FallbackHeaders会在header中指定的key上添加异常信息:

  - id: ingredients
1
2
uri: lb://ingredients
- Path=//ingredients/
    - name: CircuitBreaker
      args:
1
2
name: fetchIngredients
fallbackUri: forward:/fallback
  - id: ingredients-fallback
1
2
uri: http://localhost:9994
- Path=/fallback
    - name: FallbackHeaders
      args:
1
executionExceptionTypeHeaderName: Test-Header
1
2
3
4
5
6
7
8
9
  
##### MapRequestHeader

MapRequestHeader用于header中的键值对复制,如下配置的意思是:如果请求header中有<font color="blue">Blue</font>就新增名为<font color="red">X-Request-Red</font>的key,其值和<font color="blue">Blue</font>的值一样


#服务端口
- MapRequestHeader=Blue, X-Request-Red

如下图,请求header中有Blue:

再看服务提供方的日志,显示header中多了X-Request-Red:

1
如果请求的header中已经存在<font color="blue">X-Request-Red</font>会出现什么情况呢?如下图,咱们把<font color="blue">X-Request-Red</font>写在请求header中: 

在服务提供方打断点,可以发现神奇的一幕,header中的所有key,对应的值其实都是集合,只是大多数情况下集合里面只有一个元素,而MapRequestHeader新增的元素会被放入这个集合,不会影响原有内容:

PrefixPath

PrefixPath很好理解,就是转发到服务提供者的时候,给path加前缀
例如我这边服务提供者原始地址是http://127.0.0.1:8082/hello/str配置如下,如果我给网关配置PrefixPath=hello,那么访问网关的时候,请求路径中就不需要hello了,配置如下:

#服务端口

1
2
- Path=/str
- PrefixPath=/hello
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  

如下图,请求路径无需<font color="blue">hello</font>:


##### PreserveHostHeader

PreserveHostHeader在转发请求到服务提供者的时候,会保留host信息(否则就只能由HTTP client来决定了)
先看不使用PreserveHostHeader的效果,如下图,服务提供者收到的请求header中的host就是网关配置的信息:


加上PreserveHostHeader试试,如下图红框,是真正的host信息:


##### RequestRateLimiter

RequestRateLimiter用于限流,涉及内容较多,就放在单独的章节深入研究吧

##### RedirectTo

RedirectTo的功能简单直白:跳转到指定位置,下面的配置中,uri字段明显是一个无效的地址,但请求还是会被RedirectTo转发到指定位置去:


#服务端口
uri: http://127.1.1.1:11111
- RedirectTo=302, http://127.0.0.1:8082/hello/str

RemoveRequestHeader

RemoveRequestHeader很好理解,删除请求header中的指定值
下面的配置会删除请求header中的foo:

#服务端口

1
- RemoveRequestHeader=foo
1
2
3
4
5
6
7
8
9
10
  
##### RemoveResponseHeader

RemoveResponseHeader删除响应header中的指定值
下面的配置会删除响应header中的foo:


#服务端口
- RemoveResponseHeader=foo

RemoveRequestParameter

RemoveRequestParameter 删除请求参数中的指定参数
下面的配置会删除请求参数中的foo:

#服务端口

1
- RemoveRequestParameter=foo1
1
2
3
4
5
6
7
8
9
  
##### RewritePath

RewritePath非常实用,将请求参数中的路径做变换
下面的配置会将<font color="blue">/test/str</font>转成<font color="blue">/hello/str</font>:


```xml
#服务端口
      - Path=/test/
      - RewritePath=/test/?(?<segment>.*), /hello/$\{segment}
1

请求如下,可见path中的test会被网关修改成hello,变成正确的请求路径:

RewriteLocationResponseHeader

RewriteLocationResponseHeader用于改写response中的location信息
配置如下,一共是四个参数:stripVersionMode、locationHeaderName、hostValue、protocolsRegex
例如请求是API.example.com/some/object/name,response的location是object-service.prod.example.net/v2/some/object/id,最终会被下面的filter改写为API.example.com/some/object/id

  - id: rewritelocationresponseheader_route
    uri: http://example.org
    - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  

stripVersionMode的策略一共三种:

NEVER_STRIP:不执行 AS_IN_REQUEST :原始请求没有vesion,就执行 ALWAYS_STRIP :固定执行

Location用于替换host:port部分,如果没有就是用Request中的host

protocolsRegex用于匹配协议,如果匹配不上,name过滤器啥都不做

##### RewriteResponseHeader

RewriteResponseHeader很好理解:修改响应header,参数有三个:header的key,匹配value的正则表达式,修改value的结果
```json
下面的配置表示修改响应header中<font color="blue">X-Response-Red</font>这个key的value,找到password=xxx的内容,改成password=*

#服务端口

1
- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=*
1
2
3
4
5
6
7
8
9
  
##### SecureHeaders

SecureHeaders会在响应的header中添加很多和安全相关的内容,配置如下:


#服务端口
- SecureHeaders

响应如下,可见header中添加了很多信息:

如果不想返回上图中的某些内容,可以在配置文件中关闭掉,如下图红框,x-frame-options和strict-transport-security两项被设置为不返回了:

再试试,得到如下响应,可见x-frame-options和strict-transport-security都没有返回:

SetPath
1
SetPath配合predicates使用,下面的配置会将请求<font color="blue">/test/str</font>改成<font color="blue">/hello/str</font>,可见这个segment是在predicates中赋值的,然后再filters中拿来用: 

#服务端口
filter:
secure-headers:
disable:
- x-frame-options
- strict-transport-security

1
2
- Path=/test/{segment}
- SetPath=/hello/{segment}
1
2
3
4
5
6
7
8
9
  
##### SetRequestHeader

SetRequestHeader顾名思义,就是改写请求的header,将指定key改为指定value,如果该key不存在就创建:


#服务端口
- SetRequestHeader=X-Request-Red, Blue

和SetPath类似,SetRequestHeader也可以和predicates配合,在predicates中定义的变量可以用在SetRequestHeader中,如下所示,当请求是/hello/str的时候,header中X-Request-Red的值就是Blue-str

#服务端口

1
2
- Path=/hello/{segment}
- SetRequestHeader=X-Request-Red, Blue-{segment}
1
2
3
4
5
6
7
8
9
  
##### SetResponseHeader

SetResponseHeader顾名思义,就是改写响应的header,将指定key改为指定value,如果该key不存在就创建:


#服务端口
- SetResponseHeader=X-Request-Red, Blue

SetStatus

SetStatus很好理解:控制返回code,下面的设置会返回500:

#服务端口

1
- SetStatus=500
1
2
3
4
5
6
7
8
9
10
11
12
 

测试效果如下图,服务提供者的内容会正常返回,但是返回码已经被改为500了:


如果您想用SetStatus修改返回码,同时又不想丢掉真实的返回码,可以增加如下配置,这样真实的返回码被放在名为<font color="blue">original-status-header-name</font>的key中了:


#服务端口
set-status:
original-status-header-name: aaabbbccc

StripPrefix

StripPrefix是个很常用的filter,例如请求是/aaa/bbb/hello/str,我们要想将其转为/hello/str,用StripPrefix=2即可,前面两级path都被删掉了:

#服务端口

1
2
- Path=/aaa/**
- StripPrefix=2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  

如下图,响应正常:


##### Retry

顾名思义,Retry就是重试,需要以下参数配合使用:


retries:重试次数


exceptions:遇到什么样的异常才重试
backoff:重试策略,由多个参数构成,例如firstBackoff




- id: retry_test
uri: http://localhost:8080/flakey
- Host=*.retry.com
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false

RequestSize
1
RequestSize也很常用:控制请求大小,可以使用<font color="blue">KB</font>或者<font color="blue">MB</font>等单位,超过这个大小就会返回413错误(Payload Too Large), 
  - id: request_size_route
1
2
uri: http://localhost:8080/upload
- Path=/upload
    - name: RequestSize
      args:
1
maxSize: 5000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  

注意,如果没有设置RequestSize,Spring Cloud Gateway默认的上限是<font color="red">5MB</font>

##### SetRequestHostHeader

SetRequestHostHeader会修改请求header中的host值
下面的配置,会将请求header中的host改为<font color="blue">aaabbb</font>


#服务端口
- name: SetRequestHostHeader
args:
host: aaabbb

1
在服务提供者的代码中打断点,如下图,可见host已经被改为<font color="blue">aaabbb</font> 
ModifyRequestBody

ModifyRequestBody用于修改请求的body内容,这里官方推荐用代码来配置,如下所示,请求body中原本是字符串,结果被改成了Hello对象的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  @Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
.build();
}

static class Hello {
String message;

public Hello() { }

public Hello(String message) {
this.message = message;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
}

ModifyResponseBody

ModifyResponseBody与前面的ModifyRequestBody类似,官方建议用代码实现,下面的代码作用是将响应body的内容改为全部大写:

1
2
3
4
@Bean
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.modifyResponseBody(String.class, String.class,
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))

}

1
2
3
4
5
6
7
8
9
10
11
  
##### TokenRelay

在使用第三方鉴权的时候,如OAuth2,用TokenRelay可以将第三方的token转发到服务提供者那里去:


- id: resource
uri: http://localhost:9000
- Path=/resource
- TokenRelay=

1
记得还要添加jar包依赖<font color="blue">org.springframework.boot:spring-boot-starter-oauth2-client</font> 
设置全局filter

前面的例子中,所有filter都放在路由策略中,配合predicates一起使用的,如果您想配置全局生效的filter,可以在配置文件中做以下设置,下面的配置表示AddResponseHeader和PrefixPath会处理所有请求,和路由设置无关:

1
2
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
  - PrefixPath=/httpbin

 
 至此,大部分内置过滤器咱们已经了解了,有几个略微复杂的留待后面的章节深入学习 
 
##### 你不孤单,欣宸原创一路相伴
 
 Java系列 
 Spring系列 
 Docker系列 
 kubernetes系列 
 数据库+中间件系列 
 DevOps系列 
 
##### 欢迎
                                      

本文标题: SpringCloudGateway实战之五内

发布时间: 2019年02月16日 00:00

最后更新: 2025年12月30日 08:54

原始链接: https://haoxiang.eu.org/ee3eb93a/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码