本文基於 spring cloud gateway 2.0.1
1、GatewayFilterFactory 簡介
路由過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。 路徑過濾器的范圍限定為特定路徑。 Spring Cloud Gateway包含許多內置的GatewayFilter工廠。
網關過濾器工廠接口有多個實現類,在每個 GatewayFilterFactory 實現類的 apply( T config) 方法里,都聲明了一個實現 GatewayFilter 的內部類。
內置的過濾器工廠一共有22個,分別位於 org.springframework.cloud.gateway.filter.factory及org.springframework.cloud.gateway.filter.factory.rewrite包中
2、GatewayFilterFactory 分類
過濾器 有 20 多個 實現 類, 包括 頭部 過濾器、 路徑 類 過濾器、 Hystrix 過濾器 和 變更 請求 URL 的 過濾器, 還有 參數 和 狀態 碼 等 其他 類型 的 過濾器。
內置的過濾器工廠有22個實現類,包括 頭部過濾器、路徑過濾器、Hystrix 過濾器 、請求URL 變更過濾器,還有參數和狀態碼等其他類型的過濾器。根據過濾器工廠的用途來划分,可以分為以下幾種:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter和Hystrix
3、GatewayFilterFactory 源碼
由接口名稱上的注解 @FunctionalInterface 可知,GatewayFilterFactory是一個函數式接口,其中 default 類型的方法 name 用來對過濾器進行標准化命名,apply 方法用於定義具體的過濾操作,泛型 C 是在各個實現類中的配置對象
@FunctionalInterface
public interface GatewayFilterFactory<C> extends ShortcutConfigurable, Configurable<C> {
String NAME_KEY = "name";
String VALUE_KEY = "value";
// useful for javadsl
default GatewayFilter apply(Consumer<C> consumer) {
C config = newConfig();
consumer.accept(config);
return apply(config);
}
default Class<C> getConfigClass() {
throw new UnsupportedOperationException("getConfigClass() not implemented");
}
@Override
default C newConfig() {
throw new UnsupportedOperationException("newConfig() not implemented");
}
GatewayFilter apply(C config);
default String name() {
//TODO: deal with proxys
return NameUtils.normalizeFilterFactoryName(getClass());
}
@Deprecated
default ServerHttpRequest.Builder mutate(ServerHttpRequest request) {
return request.mutate();
}
}
3.1、GatewayFilterFactory 抽象實現類
由 GatewayFilterFactory 類圖可知,GatewayFilterFactory主要有三個抽象類:
AbstractGatewayFilterFactory:
HystrixGatewayFilterFactory
ModifyRequestBodyGatewayFilterFactory
ModifyResponseBodyGatewayFilterFactory
PrefixPathGatewayFilterFactory
PreserveHostHeaderGatewayFilterFactory
RedirectToGatewayFilterFactory
RemoveRequestHeaderGatewayFilterFactory
RemoveResponseHeaderGatewayFilterFactory
RequestRateLimiterGatewayFilterFactory
RetryGatewayFilterFactory
RewritePathGatewayFilterFactory
SaveSessionGatewayFilterFactory
SecureHeadersGatewayFilterFactory
SetPathGatewayFilterFactory
SetStatusGatewayFilterFactory
StripPrefixGatewayFilterFactory
AbstractNameValueGatewayFilterFactory(繼承自AbstractGatewayFilterFactory)
AddRequestHeaderGatewayFilterFactory
AddRequestParameterGatewayFilterFactory
AddResponseHeaderGatewayFilterFactory
SetRequestHeaderGatewayFilterFactory
SetResponseHeaderGatewayFilterFactory
AbstractChangeRequestUriGatewayFilterFactory(繼承自AbstractGatewayFilterFactory)
RequestHeaderToRequestUriGatewayFilterFactory
AbstractNameValueGatewayFilterFactory
該抽象類用於提供通用的方法給鍵值對參數類型的網關過濾器,接收兩個參數,如
AddRequestHeader 這種類型的過濾器
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
AbstractChangeRequestUriGatewayFilterFactory
改變請求的 URI 過濾器,該過濾器通過方法 determineRequestUri( ServerWebExchange,T)實現改變請求URI的邏輯
4、GatewayFilterFactory 實現類
4.1、Header 類過濾器
4.1.1、AddRequestHeaderGatewayFilterFactory
增加請求的頭部信息,並將頭部傳遞到下游。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
這將為所有匹配請求的下游請求標頭添加X-Request-Foo:Bar頭。
4.1.2、RemoveRequestHeaderGatewayFilterFactory
在請求發送到下游之前,為匹配的請求移除設置的頭部信息。
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
請求發送到下游之前刪除X-Response-Foo頭。
4.1.3、AddResponseHeaderGatewayFilterFactory
將會為匹配的請求增加響應頭部,傳遞到下游的相應頭部。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
這會將X-Response-Foo:Bar 頭添加到所有匹配請求的下游響應標頭中。
4.1.4、RemoveResponseHeaderGatewayFilterFactory
將相應結果返給客戶端之前,將會移除設置的響應頭部信息。
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
這將在響應返回到網關客戶端之前從響應中刪除X-Response-Foo標頭。
4.1.5、SetRequestHeaderGatewayFilterFactory
當請求經過網關轉發時,該過濾器將會用給定的名字替換所有的頭部信息
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetRequestHeader=X-Response-Foo, Bar
使用 X-Response-Foo:Bar替換請求頭中對應屬性的值
4.1.6、SetResponseHeaderGatewayFilterFactory
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
此GatewayFilter將替換具有給定名稱的所有標頭,而不是添加。 因此,如果下游服務器以X-Response-Foo:1234響應,則將替換為X-Response-Foo:Bar,這是網關客戶端將接收的內容。
4.1.7、PreserveHostHeaderGatewayFilterFactory
PreserveHostHeader GatewayFilter Factory沒有參數。 此過濾器設置路由過濾器將檢查的請求屬性,以確定是否應發送原始主機頭,而不是http客戶端確定的主機頭。
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: http://example.org
filters:
- PreserveHostHeader
4.1.8、RequestHeaderToRequestUriGatewayFilterFactory
spring:
cloud:
gateway:
enabled: true
discovery:
locator:
enabled: true
routes:
- id: request_header_to_request_uri_route
uri: http://example.org
filters:
- RequestHeaderToRequestUri=X-New-Url
當請求 http://example.org 時,會根據X-New-Url來進行新的url路由
4.1.9、SecureHeadersGatewayFilterFactory
當使用該過濾器時,會默認為請求頭添加以下屬性:
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
要更改默認值,請在spring.cloud.gateway.filter.secure-headers命名空間中設置相應的屬性:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
關於這些請求頭的含義可參考該文章:https://blog.appcanary.com/2017/http-security-headers.html
4.2、Parameter 類過濾器
4.2.1、AddRequestParameterGatewayFilterFactory
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://example.org
filters:
- AddRequestParameter=foo, bar
這會將foo = bar添加到下游請求的所有匹配請求的查詢字符串中。
4.3、Path 類過濾器
4.3.1、PrefixPathGatewayFilterFactory
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- PrefixPath=/mypath
這將使/mypath前綴為所有匹配請求的路徑。 所以對/hello的請求會被發送到/mypath / hello。
4.3.2、RewritePathGatewayFilterFactory
RewritePath網關過濾器工廠采用路徑正則表達式參數和替換參數。 這使用Java正則表達式來靈活地重寫請求路徑。
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
對於/ foo / bar的請求路徑,這將在發出下游請求之前將路徑設置為/ bar。 注意由於YAML規范,$ \替換為$。
4.3.3、SetPathGatewayFilterFactory
SetPath GatewayFilter Factory采用路徑模板參數。 它提供了一種通過允許模板化路徑段來操作請求路徑的簡單方法。 這使用了Spring Framework中的uri模板。 允許多個匹配的段。
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: http://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
對於/ foo / bar的請求路徑,這將在發出下游請求之前將路徑設置為/ bar。
4.3.4、StripPrefixGatewayFilterFactory
StripPrefix網關過濾器工廠采用一個參數StripPrefix。 StripPrefix參數表示在將請求發送到下游之前從請求中剝離的路徑個數。
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
當通過網關向/name/bar/foo發出請求時,對nameservice的請求將類似於http://nameservice/foo。
4.4、Body 類過濾器
4.4.1、ModifyRequestBodyGatewayFilterFactory
用於修改請求頭信息
它應該刪除原始的Content-Length標頭,並在需要時更新Content-Type。
4.4.2、ModifyResponseBodyGatewayFilterFactory
用於修改響應體信息
4.5、Status 類過濾器
4.5.1、SetStatusGatewayFilterFactory
SetStatus GatewayFilter Factory采用單個狀態參數。 它必須是有效的Spring HttpStatus。 它可以是整數值404或枚舉NOT_FOUND的字符串表示。
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
在任何一種情況下,響應的HTTP狀態都將設置為401。
4.6、Session 類過濾器
4.6.1、SaveSessionGatewayFilterFactory
SaveSession GatewayFilter Factory在轉發下游調用之前強制執行WebSession :: save操作。 當使用Spring Session與懶加載數據存儲之類的東西時,這是特別有用的,並且需要確保在轉發調用之前已保存會話狀態。
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
如果要將Spring Security與Spring Session集成,並且希望確保將安全性詳細信息轉發到遠程進程,則這很關鍵。
4.7、Redirect 類過濾器
4.7.1、RedirectToGatewayFilterFactory
RedirectTo GatewayFilter Factory采用status和url參數。 狀態應該是300系列重定向http代碼,例如301. url應該是有效的URL。 這將是Location標頭的值。
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- RedirectTo=302, http://acme.org
將發送帶有Location:http://acme.org 的請求頭屬性且狀態302的請求,以執行重定向。
4.8、Retry 類過濾器
4.8.1、RetryGatewayFilterFactory
該過濾器有三個參數:
- retries: 重試次數
- statuses: 應該重試的HTTP狀態代碼,使用org.springframework.http.HttpStatus表示
- methods: 應該重試的HTTP方法,使用org.springframework.http.HttpMethod表示
- series: 要重試的一系列狀態代碼,使用org.springframework.http.HttpStatus.Series表示
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
4.9、RateLimiter 類過濾器
4.9.1、RequestRateLimiterGatewayFilterFactory
RequestRateLimiter GatewayFilter Factory使用RateLimiter實現來確定是否允許當前請求繼續。 如果不是,則返回HTTP 429 - Too Many Requests(默認情況下)的狀態。
此過濾器采用可選的keyResolver參數和特定於速率限制器的參數(參見下文)。
keyResolver是一個實現KeyResolver接口的bean。 在配置中,使用SpEL按名稱引用bean。 #{@ myKeyResolver}是一個引用名為myKeyResolver的bean的SpEL表達式。
KeyResolver.java.
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver接口允許可插拔策略派生用於限制請求的密鑰。 在未來的里程碑中,將會有一些KeyResolver實現。
KeyResolver的默認實現是PrincipalNameKeyResolver,它從ServerWebExchange檢索Principal並調用Principal.getName()。
RequestRateLimiter不能通過“快捷方式”表示法進行配置。 以下示例無效
application.properties
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
4.10、Hystrix 類過濾器
4.10.1、HystrixGatewayFilterFactory
Hystrix是Netflix的一個庫,它實現了斷路器模式。 Hystrix GatewayFilter允許您將斷路器引入網關路由,保護您的服務免受級聯故障的影響,並允許您在下游故障時提供回退響應。
要在項目中啟用Hystrix GatewayFilters,請在Spring Cloud Netflix上添加對spring-cloud-starter-netflix-hystrix的依賴關系。
Hystrix GatewayFilter Factory需要單個名稱參數,該參數是HystrixCommand的名稱。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://example.org
filters:
- Hystrix=myCommandName
這將使用命令名myCommandName將剩余的過濾器包裝在HystrixCommand中。
Hystrix過濾器還可以接受可選的fallbackUri參數。 目前,僅支持forward:schemed URIs。 如果調用了回退,請求將被轉發到與URI匹配的控制器。
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint
當調用Hystrix回調時,這將轉發到/ incaseoffailureuset這個URI。 請注意,此示例還通過目標URI上的lb前綴演示(可選)Spring Cloud Netflix Ribbon負載平衡。
主要目的是將fallbackUri用於網關應用程序內的內部控制器或處理程序。 但是,也可以將請求重新路由到外部應用程序中的控制器或處理程序,如下所示:
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
在此示例中,網關應用程序中沒有回調端點或處理程序,但是,在http://localhost:9994下注冊的另一個應用程序中有一個。
如果請求被轉發到回調地址時,Hystrix網關過濾器還會提供導致它的Throwable。 它作為ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR屬性添加到ServerWebExchange中,可以在處理網關應用程序中的回退時使用該屬性。
對於外部控制器/處理程序方案,可以添加包含異常詳細信息的標頭。 您可以在FallbackHeaders GatewayFilter Factory部分中找到有關它的更多信息。
Hystrix設置(例如超時)可以使用全局默認值配置,也可以使用應用程序屬性逐個路徑配置,如Hystrix wiki中所述。
如果要為上面的示例路由設置5秒超時,將使用以下配置:
application.yml
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000