【轉載】Spring Cloud Gateway-過濾器工廠詳解(GatewayFilter Factories)
http://www.imooc.com/article/290816
TIPS
本文基於
Spring Cloud Greenwich SR2
,理論支援Spring Cloud Greenwich SR1
,其中的新特性標註出來了。
這一節來探討Spring Cloud Gateway內建的Filter工廠。包括:
1 AddRequestHeader GatewayFilter Factory
2 AddRequestParameter GatewayFilter Factory
3 AddResponseHeader GatewayFilter Factory
4 DedupeResponseHeader GatewayFilter Factory
6 FallbackHeaders GatewayFilter Factory
7 PrefixPath GatewayFilter Factory
8 PreserveHostHeader GatewayFilter Factory
9 RequestRateLimiter GatewayFilter Factory
10 RedirectTo GatewayFilter Factory
11 RemoveHopByHopHeadersFilter GatewayFilter Factory
12 RemoveRequestHeader GatewayFilter Factory
14 RewritePath GatewayFilter Factory
15 RewriteResponseHeader GatewayFilter Factory
16 SaveSession GatewayFilter Factory
17 SecureHeaders GatewayFilter Factory
18 SetPath GatewayFilter Factory
19 SetResponseHeader GatewayFilter Factory
20 SetStatus GatewayFilter Factory
22 Retry GatewayFilter Factory
23 RequestSize GatewayFilter Factory
24 Modify Request Body GatewayFilter Factory
25 Modify Response Body GatewayFilter Factory
26 Default Filters
技巧
-
斷點打在
org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter
,就可以除錯Gateway轉發的具體細節了。 -
新增如下配置,可觀察到一些請求細節:
logging: level: org.springframework.cloud.gateway: trace org.springframework.http.server.reactive: debug org.springframework.web.reactive: debug reactor.ipc.netty: debug
1 AddRequestHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
為原始請求新增名為X-Request-Foo
,值為Bar
的請求頭。
2 AddRequestParameter GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=foo, bar
為原始請求新增請求引數foo=bar
3 AddResponseHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
新增名為X-Request-Foo
,值為Bar
的響應頭。
4 DedupeResponseHeader GatewayFilter Factory
TIPS
Spring Cloud Greenwich SR2提供的新特性,低於這個版本無法使用。
強烈建議閱讀一下類org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory上的註釋,比官方文件寫得還好。
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_FIRST
剔除重複的響應頭。
舉個例子:
我們在Gateway以及微服務上都設定了CORS(解決跨域)header,如果不做任何配置,請求 -> 閘道器 -> 微服務,獲得的響應就是這樣的:
Access-Control-Allow-Credentials: true, true
Access-Control-Allow-Origin: https://musk.mars, https://musk.mars
也就是Header重複了。要想把這兩個Header去重,只需設定成如下即可。
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
也就是說,想要去重的Header如果有多個,用空格分隔即可;
去重策略:
RETAIN_FIRST: 預設值,保留第一個值
RETAIN_LAST: 保留最後一個值
RETAIN_UNIQUE: 保留所有唯一值,以它們第一次出現的順序保留
5 Hystrix GatewayFilter Factory
TIPS
Hystrix是Spring Cloud第一代中的容錯元件,不過已經進入維護模式(相關文章:Spring Cloud Netflix專案進入維護模式之我見),未來,Hystrix會被Spring Cloud移除掉,取而代之的是Alibaba Sentinel/Resilience4J。
所以本文不做詳細探討了,但Gateway整合Hystrix其實包含了很多姿勢。請感興趣的同學自行前往官方文件瞭解詳情:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#hystrix
。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: https://example.org
filters:
- Hystrix=myCommandName
6 FallbackHeaders GatewayFilter Factory
TIPS
也是對Hystrix的支援,不做詳細探討了,請感興趣的同學自行前往官方文件瞭解詳情:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#fallback-headers
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: Hystrix
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
7 PrefixPath GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
為匹配的路由新增字首。例如:訪問${GATEWAY_URL}/hello
會轉發到https://example.org/mypath/hello
。
8 PreserveHostHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: https://example.org
filters:
- PreserveHostHeader
如果不設定,那麼名為Host
的Header由Http Client控制;如果設定了,那麼會設定一個請求屬性(preserveHostHeader=true),路由過濾器會檢查從而去判斷是否要傳送原始的、名為Host的Header。
9 RequestRateLimiter GatewayFilter Factory
TIPS
在視訊Spring Cloud Gateway一章,限流一節會詳細講解。也可閱讀官方文件
https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_requestratelimiter_gatewayfilter_factory
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
10 RedirectTo GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
# 配置成HTTP狀態碼, URL的形式
- RedirectTo=302, http://www.itmuch.com
- HTTP狀態碼應該是HTTP狀態碼300序列,例如301
- URL必須是合法的URL,並且該值會作為名為
Location
的Header。
上面配置表達的意思是:${GATEWAY_URL}/hello
會重定向到https://ecme.org/hello
,並且攜帶一個Location:http://www.itmuch.com
的Header。
11 RemoveHopByHopHeadersFilter GatewayFilter Factory
spring.cloud.gateway.filter.remove-hop-by-hop.headers: Connection,Keep-Alive
移除轉發請求的Header,多個用,
分隔。預設情況下,移除如下Header。這些Header是由IETF組織規定的。
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailer
- Transfer-Encoding
- Upgrade
12 RemoveRequestHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
為原始請求刪除名為X-Request-Foo
的請求頭。
13 RemoveResponseHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
刪除名為X-Request-Foo
的響應頭。
14 RewritePath GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/foo/**
filters:
# 配置成原始路徑正則, 重寫後的路徑的正則
- RewritePath=/foo/(?<segment>.*), /$\{segment}
重寫請求路徑。如上配置,訪問/foo/bar
會將路徑改為/bar
再轉發,也就是會轉發到https://example.org/bar
。需要注意的是,由於YAML語法,需用$\
替換$
。
15 RewriteResponseHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: https://example.org
filters:
- RewriteResponseHeader=X-Response-Foo, password=[^&]+, password=***
如果名為X-Response-Foo
的響應頭的內容是/42?user=ford&password=omg!what&flag=true
,則會被修改為/42?user=ford&password=***&flag=true
。
16 SaveSession GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: save_session
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
在轉發到後端微服務請求之前,強制執行WebSession::save
操作。用在那種像Spring Session
延遲資料儲存(筆者注:資料不是立刻持久化)的,並希望在請求轉發前確保session狀態儲存情況。
如果你將Spring Secutiry
於Spring Session
整合使用,並想確保安全資訊都傳到下游機器,你就需要配置這個filter。
17 SecureHeaders GatewayFilter Factory
新增一系列起安全作用的響應頭。Spring Cloud Gateway參考了這篇部落格的建議:https://blog.appcanary.com/2017/http-security-headers.html
預設會新增如下Header(包括值):
X-Xss-Protection:1; mode=block
Strict-Transport-Security:max-age=631138519
X-Frame-Options:DENY
X-Content-Type-Options:nosniff
Referrer-Policy:no-referrer
Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'
X-Download-Options:noopen
X-Permitted-Cross-Domain-Policies:none
如果你想修改這些Header的值,可使用如下配置:
字首:spring.cloud.gateway.filter.secure-headers
上面的header對應的字尾:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
例如:spring.cloud.gateway.filter.secure-headers.xss-protection-header: 你想要的值
如果想禁用某些Header,可使用如下配置:spring.cloud.gateway.filter.secure-headers.disable
,多個用,
分隔。例如:spring.cloud.gateway.filter.secure-headers.disable=frame-options,download-options
。
18 SetPath GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
採用路徑template
引數,通過請求路徑的片段的模板化,來達到操作修改路徑的母的,執行多個路徑片段模板化。
如上配置,訪問${GATEWAY_PATH}/foo/bar
,則對於後端微服務的路徑會修改為/bar
。
19 SetResponseHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
如果後端服務響應帶有名為X-Response-Foo
的響應頭,則將值改為替換成Bar
。
20 SetStatus GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: http://example.org
filters:
- SetStatus=BAD_REQUEST
- id: setstatusint_route
uri: http://example.org
filters:
- SetStatus=401
修改響應的狀態碼,值可以是數字,也可以是字串。但一定要是SpringHttpStatus
列舉類中的值。如上配置,兩種方式都可以返回HTTP狀態碼401。
21 StripPrefix GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
數字表示要截斷的路徑的數量。如上配置,如果請求的路徑為/name/bar/foo
,則路徑會修改為/foo
,也就是會截斷2個路徑。
22 Retry GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
針對不同的響應做重試,可配置如下引數:
retries
: 重試次數statuses
: 需要重試的狀態碼,取值在org.springframework.http.HttpStatus
中methods
: 需要重試的請求方法,取值在org.springframework.http.HttpMethod
中series
: HTTP狀態碼系列,取值在org.springframework.http.HttpStatus.Series
中
23 RequestSize GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
# 單位位元組
maxSize: 5000000
為後端服務設定收到的最大請求包大小。如果請求大小超過設定的值,則返回413 Payload Too Large
。預設值是5M
24 Modify Request Body GatewayFilter Factory
TIPS
該過濾器處於
BETA
狀態,未來API可能會變化,生產環境請慎用。
可用於在Gateway將請求傳送給後端微服務之前,修改請求體內容。該過濾器只能通過程式碼配置,不支援在配置檔案設定。示例:
@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) {
this.message = message;
}
}
25 Modify Response Body GatewayFilter Factory
TIPS
該過濾器處於
BETA
狀態,未來API可能會變化,生產環境請慎用。
可用於修改響應體內容。該過濾器只能通過程式碼配置,不支援在配置檔案設定。示例:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyResponseBody(String.class, String.class,
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
.build();
}
26 Default Filters
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
- PrefixPath=/httpbin
如果你想為所有路由新增過濾器,可使用該屬性。
本文首發
http://www.itmuch.com/spring-cloud-gateway/gateway-filter-factory