目錄
6.1.AddRequestHeader
6.2.AddRequestHeadersIfNotPresent
6.3.AddRequestParameter
6.4.AddResponseHeader
6.5.CircuitBreaker
6.5.1. 熔斷指定的狀態碼
6.6.CacheRequestBody
6.7.DedupeResponseHeader
6.8.FallbackHeaders
6.9.JsonToGrpc
6.10.LocalResponseCache
6.11.MapRequestHeader
6.12.ModifyRequestBody
6.13.ModifyResponseBody
6.14.PrefixPath
6.15.PreserveHostHeader
6.16.RedirectTo
6.17.RemoveJsonAttributesResponseBody
6.18.RemoveRequestHeader
6.19.RemoveRequestParameter
6.20.RemoveResponseHeader
6.21.RequestHeaderSize
6.22.RequestRateLimiter
6.22.1. RedisRateLimiter
6.23.RewriteLocationResponseHeader
6.24.RewritePath
6.25.RewriteResponseHeader
6.26.SaveSession
6.27.SecureHeaders
6.28.SetPath
6.29.SetRequestHeader
6.30.SetResponseHeader
6.31.SetStatus
6.32.StripPrefix
6.33.Retry
6.34.RequestSize
6.35.SetRequestHostHeader
6.36.TokenRelay
6.37. 默認 Filter
路由(Route)過濾器(Filter)允許以某種方式修改傳入的 HTTP 請求或傳出的 HTTP 響應。路由過濾器的范圍是一個特定的路由。Spring Cloud Gateway 包括許多內置的 GatewayFilter 工廠。
關于如何使用以下任何過濾器的更詳細的例子,請看 單元測試。
6.1.AddRequestHeader
AddRequestHeader GatewayFilter 工廠需要一個 name 和 value 參數。下面的例子配置了一個 AddRequestHeader GatewayFilter。
Example 14. application.yml
spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgfilters:- AddRequestHeader=X-Request-red, blue
這個列表將 X-Request-red:blue header添加到所有匹配請求的下游請求的header信息中。
AddRequestHeader 知道用于匹配路徑或主機的URI變量。URI變量可以在值中使用,并在運行時被擴展。下面的例子配置了一個 AddRequestHeader GatewayFilter,它使用一個變量。
Example 15. application.yml
spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgpredicates:- Path=/red/{segment}filters:- AddRequestHeader=X-Request-Red, Blue-{segment}
6.2.AddRequestHeadersIfNotPresent
AddRequestHeadersIfNotPresent GatewayFilter 工廠接受一個由冒號分隔的 name 和 value 鍵值對的集合。下面的例子配置了一個 AddRequestHeadersIfNotPresent GatewayFilter。
Example 16. application.yml
spring:cloud:gateway:routes:- id: add_request_headers_routeuri: https://example.orgfilters:- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green
這個列表為所有匹配的請求在下游請求的header信息中添加了兩個header信息 X-Request-Color-1:blue 和 X-Request-Color-2:green。這類似于 AddRequestHeader 的工作方式,但與 AddRequestHeader 不同的是,它只在header 信息不存在的情況下才會這樣做。否則,客戶端請求中的原始值將被發送。
此外,要設置一個多值header,可以多次使用header的名稱,如 AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-1:green。
AddRequestHeadersIfNotPresent 也支持URI變量,用于匹配路徑或主機。URI變量可以在值中使用,并在運行時被擴展。下面的例子配置了一個使用變量的 AddRequestHeadersIfNotPresent GatewayFilter。
Example 17. application.yml
spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgpredicates:- Path=/red/{segment}filters:- AddRequestHeadersIfNotPresent=X-Request-Red:Blue-{segment}
6.3.AddRequestParameter
AddRequestParameter GatewayFilter Factory需要一個 name 和 value 參數。下面的例子配置了一個 AddRequestParameter GatewayFilter。
Example 18. application.yml
spring:cloud:gateway:routes:- id: add_request_parameter_routeuri: https://example.orgfilters:- AddRequestParameter=red, blue
這將為所有匹配的請求在下游請求的查詢字符串中添加 red=blue。
AddRequestParameter 知道用于匹配路徑或主機的URI變量。URI變量可以在值中使用,并在運行時被擴展。下面的例子配置了一個 AddRequestParameter GatewayFilter,它使用了一個變量。
Example 19. application.yml
spring:cloud:gateway:routes:- id: add_request_parameter_routeuri: https://example.orgpredicates:- Host: {segment}.myhost.orgfilters:- AddRequestParameter=foo, bar-{segment}
6.4.AddResponseHeader
AddResponseHeader GatewayFilter 工廠需要一個 name 和 value 參數。下面的例子配置了一個 AddResponseHeader GatewayFilter。
Example 20. application.yml
spring:cloud:gateway:routes:- id: add_response_header_routeuri: https://example.orgfilters:- AddResponseHeader=X-Response-Red, Blue
這將把 X-Response-Red:Blue header添加到所有匹配請求的下游響應的header中。
AddResponseHeader 知道用于匹配路徑或主機的URI變量。URI變量可以在值中使用,并在運行時被擴展。下面的例子配置了一個 AddResponseHeader GatewayFilter,它使用了一個變量。
Example 21. application.yml
spring:cloud:gateway:routes:- id: add_response_header_routeuri: https://example.orgpredicates:- Host: {segment}.myhost.orgfilters:- AddResponseHeader=foo, bar-{segment}
6.5.CircuitBreaker
Spring Cloud CircuitBreaker GatewayFilter 工廠使用Spring Cloud CircuitBreaker API 將 Gateway 路由包裹在一個熔斷器中。Spring Cloud CircuitBreaker 支持多個可與 Spring Cloud Gateway 一起使用的庫。Spring Cloud 支持 Resilience4J 開箱即用。
要啟用 Spring Cloud CircuitBreaker 過濾器,你需要添加 spring-cloud-starter-circuitbreaker-reactor-resilience4j 依賴。下面的例子配置了一個 Spring Cloud CircuitBreaker GatewayFilter。
Example 22. application.yml
spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: https://example.orgfilters:- CircuitBreaker=myCircuitBreaker
要配置熔斷器,請參閱你所使用的底層熔斷器實現的配置。
- Resilience4J 文檔
Spring Cloud CircuitBreaker 過濾器還可以接受一個可選的 fallbackUri 參數。目前,只支持 forward: 模式的URI。如果fallback被調用,請求將被轉發到URI所匹配的控制器。下面的例子配置了這樣一個fallback。
Example 23. application.yml
spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpointfilters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThis- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
也可以通過Java來實現相同的配置,如下。
Example 24. Application.java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint").filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis")).rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088").build();
}
當熔斷器 fallback 被調用時,這個例子轉發到 /inCaseofFailureUseThis URI。請注意,這個例子還演示了(可選)Spring Cloud LoadBalancer 的負載均衡(由目標URI上的 lb 前綴定義)。
CircuitBreaker 還支持 fallbackUri 中的URI變量。這允許更復雜的路由選項,比如使用 PathPattern 表達式 轉發原始主機或URL路徑的部分。
在下面的例子中,調用 consumingServiceEndpoint/users/1 將被重定向到 inCaseOfFailureUseThis/users/1。
Example 25. application.yml
spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpoint/{*segments}filters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThis/{segments}
一般情況下是使用 fallbackUri 來定義網關應用程序中的內部controller或handler。然而,你也可以將請求重新路由到外部應用程序的controller或handler,如下所示。
Example 26. application.yml
spring:cloud:gateway:routes:- id: ingredientsuri: lb://ingredientspredicates:- Path=//ingredients/**filters:- name: CircuitBreakerargs:name: fetchIngredientsfallbackUri: forward:/fallback- id: ingredients-fallbackuri: http://localhost:9994predicates:- Path=/fallback
在這個例子中,網關應用程序中沒有 fallback 端點或處理程序。然而,在另一個應用程序中有一個,在 localhost:9994 下注冊。
在請求被轉發到 fallback 的情況下,Spring Cloud CircuitBreaker Gateway 過濾器也提供了造成這種情況的 Throwable。它作為 ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 屬性被添加到 ServerWebExchange 中,在網關應用中處理 fallback 時可以使用。
對于外部 controller/handler 的情況,可以添加帶有異常細節的header。你可以在FallbackHeaders GatewayFilter Factory 部分找到更多關于這樣做的信息。
6.5.1. 熔斷指定的狀態碼
在某些情況下,你可能想根據它所包裹的路由返回的狀態碼來熔斷。斷路器配置對象需要一個狀態碼列表,如果返回這些代碼將導致斷路器熔斷。當設置你想讓斷路器熔斷的狀態代碼時,你可以使用一個帶有狀態碼值的 int 或 HttpStatus 枚舉的字符串表示。
Example 27. application.yml
spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpointfilters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThisstatusCodes:- 500- "NOT_FOUND"
Example 28. Application.java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint").filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR")).rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088").build();
}
6.6.CacheRequestBody
有些情況下,有必要讀取請求體。由于請求體只能被讀取一次,我們需要緩存請求體。你可以使用 CacheRequestBody 過濾器來緩存請求體,然后再把它發送到下游,從 exchange 屬性中獲取請求體。
下面顯示了如何緩存請求體 GatewayFilter:
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("cache_request_body_route", r -> r.path("/downstream/**").filters(f -> f.prefixPath("/httpbin").cacheRequestBody(String.class).uri(uri)).build();
}
Example 29. application.yml
spring:cloud:gateway:routes:- id: cache_request_body_routeuri: lb://downstreampredicates:- Path=/downstream/**filters:- name: CacheRequestBodyargs:bodyClass: java.lang.String
CacheRequestBody 提取請求體并將其轉換為一個 body 類(比如前面例子中定義的 java.lang.String)。然后,CacheRequestBody 把它放在 ServerWebExchange.getAttributes() 提供的屬性中,其KEY值在 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 中定義。
這個過濾器只對HTTP(包括HTTPS)請求起作用。
6.7.DedupeResponseHeader
DedupeResponseHeader GatewayFilter 工廠接受一個 name 參數和一個可選的 strategy 參數。name 可以包含一個以空格分隔的header名稱列表。下面的例子配置了一個 DedupeResponseHeader GatewayFilter。
Example 30. application.yml
spring:cloud:gateway:routes:- id: dedupe_response_header_routeuri: https://example.orgfilters:- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
在網關CORS邏輯和下游邏輯都添加了 Access-Control-Allow-Credentials 和 Access-Control-Allow-Origin 響應頭的情況下,這將刪除重復的值。
DedupeResponseHeader 過濾器還接受一個可選的 strategy 參數。接受的值是 RETAIN_FIRST(默認)、RETAIN_LAST 和 RETAIN_UNIQUE。
6.8.FallbackHeaders
通過 FallbackHeaders 工廠,你可以在轉發到外部應用程序中的 fallbackUri 的請求的header中添加Spring Cloud CircuitBreaker的執行異常細節,如以下場景。
Example 31. application.yml
spring:cloud:gateway:routes:- id: ingredientsuri: lb://ingredientspredicates:- Path=//ingredients/**filters:- name: CircuitBreakerargs:name: fetchIngredientsfallbackUri: forward:/fallback- id: ingredients-fallbackuri: http://localhost:9994predicates:- Path=/fallbackfilters:- name: FallbackHeadersargs:executionExceptionTypeHeaderName: Test-Header
在這個例子中,在運行斷路器時發生執行異常后,請求被轉發到運行在 localhost:9994 的應用程序中的 fallback 端點或 handler。帶有異常類型、消息和(如果有)根本原因的異常類型和消息的 header 被 FallbackHeaders 過濾器添加到該請求中。
你可以通過設置以下參數的值(顯示為默認值)來覆蓋配置中header的名稱。
- executionExceptionTypeHeaderName ("Execution-Exception-Type")
- executionExceptionMessageHeaderName ("Execution-Exception-Message")
- rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")
- rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")
關于斷路器和網關的更多信息,請參見 Spring Cloud CircuitBreaker Factory 部分 。
6.9.JsonToGrpc
JSONToGRPCFilter GatewayFilter Factory 將一個JSON payload 轉換為gRPC請求。
該過濾器需要以下參數。
- protoDescriptor: Proto描述文件。
這個文件可以用 protoc 生成,并指定 --descriptor_set_out 標志。
protoc --proto_path=src/main/resources/proto/ \
--descriptor_set_out=src/main/resources/proto/hello.pb \
src/main/resources/proto/hello.proto
- protoFile: Proto定義文件。
- service: 處理請求的服務的全名稱。
- method: 處理該請求的服務中的方法名稱。
支持 streaming。 |
application.yml.
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("json-grpc", r -> r.path("/json/hello").filters(f -> {String protoDescriptor = "file:src/main/proto/hello.pb";String protoFile = "file:src/main/proto/hello.proto";String service = "HelloService";String method = "hello";return f.jsonToGRPC(protoDescriptor, protoFile, service, method);}).uri(uri))
spring:cloud:gateway:routes:- id: json-grpcuri: https://localhost:6565/testhellopredicates:- Path=/json/**filters:- name: JsonToGrpcargs:protoDescriptor: file:proto/hello.pbprotoFile: file:proto/hello.protoservice: com.example.grpcserver.hello.HelloServicemethod: hello
當通過網關向 /json/hello 發出請求時,該請求通過使用 hello.proto 中提供的定義進行轉換,發送到 com.example.grpcserver.hello.HelloService/hello,返回的響應被轉換為JSON。
默認情況下,它通過使用默認的 TrustManagerFactory 創建一個 NettyChannel。然而,你可以通過創建一個 GrpcSslConfigurer 類型的bean來定制這個 TrustManager。
@Configuration
public class GRPCLocalConfiguration {@Beanpublic GRPCSSLContext sslContext() {TrustManager trustManager = trustAllCerts();return new GRPCSSLContext(trustManager);}
}
6.10.LocalResponseCache
這個過濾器允許緩存響應體和header,遵循以下規則。
- 它只能緩存無請求體的GET請求。
- 它只對以下狀態代碼之一的響應進行緩存。HTTP 200(OK),HTTP 206(部分內容),或HTTP 301(永久移動)。
- 如果 Cache-Control header不允許,響應數據就不會被緩存(請求中存在 no-store 或響應中存在 no-store 或 private)。
- 如果響應已經被緩存,并且在 Cache-Control 頭中用 no-cache 值執行一個新的請求,它將返回一個304(未修改)的無body的響應。
這個過濾器(配置每個路由的本地響應緩存)只有在啟用了本地響應全局緩存的情況下才可用。
它接受第一個參數,用于覆蓋緩存條目過期的時間(用 s 表示秒,用 m 表示分鐘,用 h 表示小時),第二個參數用于設置該路由驅逐條目的最大緩存大小(KB、MB或GB)。
下面的列表顯示了如何添加本地響應緩存 GatewayFilter。
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {return builder.routes().route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org").filters(f -> f.prefixPath("/httpbin").localResponseCache(Duration.ofMinutes(30), "500MB")).uri(uri)).build();
}
或者,這樣:
application.yaml
spring:cloud:gateway:routes:- id: resourceuri: http://localhost:9000predicates:- Path=/resourcefilters:- LocalResponseCache=30m,500MB
這個過濾器還自動計算 HTTP Cache-Control header中的 max-age 值。只有在原始響應中存在 max-age 的情況下,才會用 timeToLive 配置參數中設置的秒數重寫該值。在連續的調用中,這個值會以響應過期前的剩余秒數重新計算。 |
6.11.MapRequestHeader
MapRequestHeader GatewayFilter 工廠接受 fromHeader 和 toHeader 參數。它創建一個新的命名header(toHeader),并從傳入的http請求的現有命名頭(fromHeader)中提取值。如果輸入的header不存在,過濾器沒有任何影響。如果新的命名header信息已經存在,它的值就會被增加新的值。下面的例子配置了一個 MapRequestHeader。
Example 32. application.yml
spring:cloud:gateway:routes:- id: map_request_header_routeuri: https://example.orgfilters:- MapRequestHeader=Blue, X-Request-Red
這將在下游請求中添加 X-Request-Red:<values> 頭,并從傳入的HTTP請求的 Blue 頭中更新數值。
6.12.ModifyRequestBody
你可以使用 ModifyRequestBody 過濾器,在網關向下游發送請求體之前對其進行修改。
這個過濾器只能通過使用Java DSL來配置。 |
下面顯示了如何使用 GatewayFilter 修改請求體:
@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;}
}
如果請求沒有正文,RewriteFilter 將被傳遞為 null。應該返回 Mono.empty() 來指定請求中缺少的主體。 |
6.13.ModifyResponseBody
你可以使用 ModifyResponseBody 過濾器來修改響應體,然后再把它送回給客戶端。
這個過濾器只能通過使用Java DSL來配置。 |
下面顯示了如何使用 GatewayFilter 修改響應體 。
@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();
}
如果響應沒有正文,RewriteFilter 將被傳遞為 null。應該返回 Mono.empty() 來指定響應中缺少的主體。 |
6.14.PrefixPath
PrefixPath GatewayFilter 工廠需要一個 prefix 參數。下面的例子配置了一個 PrefixPath GatewayFilter。
Example 33. application.yml
spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- PrefixPath=/mypath
這就把 /mypath 作為所有匹配請求的路徑的前綴。因此,一個到 /hello 的請求會被發送到 /mypath/hello。
6.15.PreserveHostHeader
PreserveHostHeader GatewayFilter 工廠沒有參數。這個過濾器設置一個請求屬性(request attribute),路由過濾器(routing filter)會檢查該屬性,以確定是否應該發送原始的主機頭,而不是由HTTP客戶端確定的主機頭。下面的例子配置了一個 PreserveHostHeader GatewayFilter。
Example 34. application.yml
spring:cloud:gateway:routes:- id: preserve_host_routeuri: https://example.orgfilters:- PreserveHostHeader
6.16.RedirectTo
RedirectTo GatewayFilter 工廠需要兩個參數,status 和 url。status 參數應該是一個300系列的重定向 HTTP 狀態碼,如301。url 參數應該是一個有效的URL。這就是 Location header 的值。對于相對重定向,你應該使用 uri: no://op 作為路由定義的uri。下面的列表配置了一個 RedirectTo GatewayFilter。
Example 35. application.yml
spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- RedirectTo=302, https://acme.org
這將發送一個帶有 Location:https://acme.org header的302狀態碼的響應,以執行重定向。
6.17.RemoveJsonAttributesResponseBody
RemoveJsonAttributesResponseBody GatewayFilter 工廠接收了一個要搜索的屬性名稱(attribute name)集合,列表中的最后一個參數可以是一個布爾值,用來刪除根級的屬性(如果該參數未定義,那就是默認值 false)或遞歸(true)。它提供了一個方便的方法,通過刪除屬性來應用于JSON body內容的轉換。
下面的例子配置了一個 RemoveJsonAttributesResponseBody GatewayFilter。
Example 36. application.yml
spring:cloud:gateway:routes:- id: removejsonattributes_routeuri: https://example.orgfilters:- RemoveJsonAttributesResponseBody=id,color
這從根層的JSON body中刪除了屬性 "id" 和 "color"。
下面的例子配置了一個 RemoveJsonAttributesResponseBody GatewayFilter,它使用了可選的最后參數。
Example 37. application.yml
spring:cloud:gateway:routes:- id: removejsonattributes_recursively_routeuri: https://example.orgpredicates:- Path=/red/{segment}filters:- RemoveJsonAttributesResponseBody=id,color,true
這將從任何級別的JSON body中移除屬性 "id" 和 "color"。
6.18.RemoveRequestHeader
RemoveRequestHeader GatewayFilter 工廠需要一個 name 參數。它是要被刪除的header的名稱。下面配置了一個 RemoveRequestHeader GatewayFilter。
Example 38. application.yml
spring:cloud:gateway:routes:- id: removerequestheader_routeuri: https://example.orgfilters:- RemoveRequestHeader=X-Request-Foo
這在向下游發送之前刪除了 X-Request-Foo 標頭。
6.19.RemoveRequestParameter
RemoveRequestParameter GatewayFilter 工廠需要一個 name 參數。它是要刪除的查詢參數的名稱。下面的例子配置了一個 RemoveRequestParameter GatewayFilter。
Example 39. application.yml
spring:cloud:gateway:routes:- id: removerequestparameter_routeuri: https://example.orgfilters:- RemoveRequestParameter=red
這將在向下游發送之前刪除 red 參數。
6.20.RemoveResponseHeader
RemoveResponseHeader GatewayFilter 工廠需要一個 name 參數。它是要被移除的 header 的名稱。下面的列表配置了一個 RemoveResponseHeader GatewayFilter。
Example 40. application.yml
spring:cloud:gateway:routes:- id: removeresponseheader_routeuri: https://example.orgfilters:- RemoveResponseHeader=X-Response-Foo
這將在響應返回到網關客戶端之前從響應中刪除 X-Response-Foo 頭。
要刪除任何類型的敏感標頭,你應該為任何你可能想這樣做的路由配置這個過濾器。此外,你可以通過使用 spring.cloud.gateway.default-filters 配置一次此過濾器,并將其應用于所有路由。
6.21.RequestHeaderSize
RequestHeaderSize GatewayFilter 工廠接受 maxSize 和 errorHeaderName 參數。maxSize 參數是請求頭(包括key和value)所允許的最大數據大小。errorHeaderName 參數設置包含錯誤信息的響應頭的名稱,默認為 "errorMessage"。下面的列表配置了一個 RequestHeaderSize GatewayFilter。
Example 41. application.yml
spring:cloud:gateway:routes:- id: requestheadersize_routeuri: https://example.orgfilters:- RequestHeaderSize=1000B
如果任何請求頭的大小超過1000字節,這將發送一個 431狀態碼的響應。
6.22.RequestRateLimiter
RequestRateLimiter GatewayFilter 工廠使用 RateLimiter 實現來確定是否允許當前請求繼續進行。如果不允許,就會返回 HTTP 429 - Too Many Requests(默認)的狀態。
這個過濾器需要一個可選的 keyResolver 參數和特定于速率限制器的參數(在本節后面描述)。
keyResolver 是一個實現了 KeyResolver 接口的Bean。在配置中,使用SpEL來引用Bean的名字。#{@myKeyResolver} 是一個SpEL表達式,它引用了一個名為 myKeyResolver 的bean。下面的列表顯示了 KeyResolver 的接口。
Example 42. KeyResolver.java
public interface KeyResolver {Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver 接口讓可插拔的策略導出限制請求的key。在未來的里程碑版本中,會有一些 KeyResolver 的實現。
KeyResolver 的默認實現是 PrincipalNameKeyResolver,它從 ServerWebExchange 中檢索 Principal 并調用 Principal.getName()。
默認情況下,如果 KeyResolver 沒有找到一個 key,請求會被拒絕。你可以通過設置 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true 或 false)和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 屬性來調整這種行為。
RequestRateLimiter 不能用 "快捷方式" 來配置。下面的例子是無效的。 Example 43. application.properties |
6.22.1. RedisRateLimiter
Redis的實現是基于 Stripe 的工作。它需要使用 spring-boot-starter-data-redis-reactive Spring Boot Starter。
使用的算法是 令牌桶算法。
redis-rate-limiter.replenishRate 屬性定義了每秒鐘允許多少個請求(不算放棄的請求)。這是令牌桶被填充的速度。
redis-rate-limiter.burstCapacity 屬性是一個用戶在一秒鐘內允許的最大請求數(不算放棄的請求)。這是令牌桶可以容納的令牌數量。將此值設置為零會阻止所有請求。
redis-rate-limiter.requestedTokens 屬性是指一個請求要花費多少令牌。這是為每個請求從桶中提取的令牌數量,默認為 1。
一個穩定的速率是通過在 replenishRate 和 burstCapacity 中設置相同的值來實現的。可以通過設置高于補給率的 burstCapacity 來允許臨時的突發。在這種情況下,速率限制器需要在突發之間允許一些時間(根據 replenishRate),因為連續兩次突發會導致請求被放棄(HTTP 429 - Too Many Requests)。下面的列表配置了一個 redis-rate-limiter。
低于 1個請求/s 的速率限制是通過將 replenishRate 設置為想要的請求數, requestTokens 設置為秒數,burstCapacity 設置為 replenishRate 和 requestTokens 的乘積來完成的。例如,設置 replenishRate=1,requestedTokens=60,burstCapacity=60,結果是1個請求/分鐘的限制。
Example 44. application.yml
spring:cloud:gateway:routes:- id: requestratelimiter_routeuri: https://example.orgfilters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 10redis-rate-limiter.burstCapacity: 20redis-rate-limiter.requestedTokens: 1
下面的例子在Java中配置了一個 KeyResolver。
Example 45. Config.java
@Bean
KeyResolver userKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
這定義了每個用戶的請求率限制為10。爆發20次是允許的,但是,在下一秒,只有10個請求可用。KeyResolver 是一個簡單的,獲得 user 請求參數。
不建議在生產中使用這個方法 |
你也可以把速率限制器定義為一個實現 RateLimiter 接口的bean。在配置中,你可以用SpEL來引用bean的名字。#{@myRateLimiter} 是一個SpEL表達式,它引用了一個名為 myRateLimiter 的 bean。下面的清單定義了一個速率限制器,它使用了前面清單中定義的 KeyResolver。
Example 46. application.yml
spring:cloud:gateway:routes:- id: requestratelimiter_routeuri: https://example.orgfilters:- name: RequestRateLimiterargs:rate-limiter: "#{@myRateLimiter}"key-resolver: "#{@userKeyResolver}"
6.23.RewriteLocationResponseHeader
RewriteLocationResponseHeader GatewayFilter 工廠修改 Location 響應頭的值,通常是為了去掉后臺的特定細節。它需要 stripVersionMode、locationHeaderName、hostValue 和 protocolsRegex 參數。下面的清單配置了一個 RewriteLocationResponseHeader GatewayFilter。
Example 47. application.yml
spring:cloud:gateway:routes:- id: rewritelocationresponseheader_routeuri: http://example.orgfilters:- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
例如,對于一個 POST api.example.com/some/object/name 的請求, Location 響應頭值 object-service.prod.example.net/v2/some/object/id 被改寫為 api.example.com/some/object/id。
stripVersionMode 參數有以下可能的值。NEVER_STRIP、AS_IN_REQUEST(默認)和 ALWAYS_STRIP。
- NEVER_STRIP: 即使最初的請求路徑不包含version,version也不會被剝離。
- AS_IN_REQUEST: 只有當原始請求路徑不包含version時,才會剝離version。
- ALWAYS_STRIP: version 總是被剝離,即使原始請求路徑包含version 。
hostValue 參數,如果提供的話,將用于替換響應的 Location 頭的 host:port 部分。如果沒有提供,則使用 Host 請求頭的值。
protocolsRegex 參數必須是一個有效的 regex String,協議名稱將與之匹配。如果沒有匹配,過濾器不做任何事情。默認是 http|https|ftp|ftps。
6.24.RewritePath
RewritePath GatewayFilter 工廠接收一個路徑 regexp 參數和一個 replacement 參數。這是用Java正則表達式來重寫請求路徑的一種靈活方式。下面的列表配置了一個 RewritePath GatewayFilter。
Example 48. application.yml
spring:cloud:gateway:routes:- id: rewritepath_routeuri: https://example.orgpredicates:- Path=/red/**filters:- RewritePath=/red/?(?<segment>.*), /$\{segment}
對于請求路徑為 /red/blue 的情況,在進行下游請求之前將路徑設置為 /blue。注意,由于YAML的規范,$ 應該被替換成 $\。
6.25.RewriteResponseHeader
RewriteResponseHeader GatewayFilter 工廠接受 name、regexp 和 replacement 參數。它使用Java正則表達式,以一種靈活的方式重寫響應頭的值。下面的例子配置了一個 RewriteResponseHeader GatewayFilter。
Example 49. application.yml
spring:cloud:gateway:routes:- id: rewriteresponseheader_routeuri: https://example.orgfilters:- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***
對于一個 /42?user=ford&password=omg!what&flag=true 的header值,在發出下游請求后,它被設置為 /42?user=ford&password=***&flag=true。因為YAML規范,你必須用 $\ 來表示 $。
6.26.SaveSession
SaveSession GatewayFilter 工廠在轉發下游調用之前強制進行 WebSession::save 操作。這在使用類似 Spring Session 的懶數據存儲時特別有用,因為你需要確保在進行轉發調用之前已經保存了Session狀態。下面的例子配置了一個 SaveSession GatewayFilter。
Example 50. application.yml
spring:cloud:gateway:routes:- id: save_sessionuri: https://example.orgpredicates:- Path=/foo/**filters:- SaveSession
如果你將 Spring Security 與 Spring Session 集成,并希望確保安全細節(security detail)已被轉發到遠程進程,這一點至關重要。
6.27.SecureHeaders
根據 這篇博客的建議,SecureHeaders GatewayFilter 工廠在響應中添加了一些頭信息。
以下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)
要改變默認值,請在 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
要禁用默認值,請用逗號分隔的值設置 spring.cloud.gateway.filter.secure-headers.disable 屬性,如下。
spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security
需要使用 secure header 的小寫全名來禁用它。?
6.28.SetPath
SetPath GatewayFilter 工廠接受一個路徑模板參數。它提供了一種簡單的方法,通過允許模板化的路徑段來操作請求路徑。這使用了 Spring Framework 的URI模板。允許多個匹配段。下面的例子配置了一個 SetPath GatewayFilter。
Example 51. application.yml
spring:cloud:gateway:routes:- id: setpath_routeuri: https://example.orgpredicates:- Path=/red/{segment}filters:- SetPath=/{segment}
對于請求路徑為 /red/blue 的情況,在進行下行請求之前,將路徑設置為 /blue。
6.29.SetRequestHeader
SetRequestHeader GatewayFilter 工廠接受 name 和 value 參數。下面的列表配置了一個 SetRequestHeader GatewayFilter。
Example 52. application.yml
spring:cloud:gateway:routes:- id: setrequestheader_routeuri: https://example.orgfilters:- SetRequestHeader=X-Request-Red, Blue
這 GatewayFilter 會替換(而不是添加)所有給定名稱的 header 信息。 因此,如果下游服務器以 X-Request-Red:1234 響應,它將被替換為 X-Request-Red:Blue,這就是下游服務會收到的。
SetRequestHeader 知道用于匹配路徑或主機的URI變量。URI變量可以在值中使用,并在運行時被擴展。下面的例子配置了一個 SetRequestHeader GatewayFilter,它使用了一個變量。
Example 53. application.yml
spring:cloud:gateway:routes:- id: setrequestheader_routeuri: https://example.orgpredicates:- Host: {segment}.myhost.orgfilters:- SetRequestHeader=foo, bar-{segment}
6.30.SetResponseHeader
SetResponseHeader GatewayFilter 工廠接受 name 和 value 參數。下面的列表配置了一個 SetResponseHeader GatewayFilter。
Example 54. application.yml
spring:cloud:gateway:routes:- id: setresponseheader_routeuri: https://example.orgfilters:- SetResponseHeader=X-Response-Red, Blue
這個 GatewayFilter 會替換(而不是添加)所有帶有給定名稱的頭信息。 因此,如果下游服務器以 X-Response-Red:1234 響應,它將被替換為 X-Response-Red:Blue,這就是網關客戶端將收到的內容。
SetResponseHeader 知道用于匹配路徑或主機的URI變量。URI變量可以在值中使用,并將在運行時被擴展。下面的例子配置了一個 SetResponseHeader GatewayFilter,它使用了一個變量。
Example 55. application.yml
spring:cloud:gateway:routes:- id: setresponseheader_routeuri: https://example.orgpredicates:- Host: {segment}.myhost.orgfilters:- SetResponseHeader=foo, bar-{segment}
6.31.SetStatus
SetStatus GatewayFilter 工廠只接受一個參數,即 status。它必須是一個有效的Spring HttpStatus。它可以是 404 的int值或枚舉的字符串表示: NOT_FOUND。下面的列表配置了一個 SetStatus GatewayFilter。
Example 56. application.yml
spring:cloud:gateway:routes:- id: setstatusstring_routeuri: https://example.orgfilters:- SetStatus=UNAUTHORIZED- id: setstatusint_routeuri: https://example.orgfilters:- SetStatus=401
在這兩種情況下,響應的HTTP狀態被設置為401。
你可以配置 SetStatus GatewayFilter,使其在響應中的頭中返回代理請求的原始HTTP狀態代碼。如果配置了以下屬性,該頭會被添加到響應中。
Example 57. application.yml
spring:cloud:gateway:set-status:original-status-header-name: original-http-status
6.32.StripPrefix
StripPrefix GatewayFilter 工廠需要一個參數,即 parts。parts 參數表示在向下游發送請求之前要從路徑中剝離的部分的數量。下面的列表配置了一個 StripPrefix GatewayFilter。
Example 58. application.yml
spring:cloud:gateway:routes:- id: nameRooturi: https://nameservicepredicates:- Path=/name/**filters:- StripPrefix=2
當通過網關向 /name/blue/red 發出請求時,向 nameservice 發出的請求看起來像 nameservice/red。
6.33.Retry
Retry GatewayFilter 工廠支持以下參數。
- retries: 應該嘗試的重試次數。
- statuses: 應該重試的HTTP狀態代碼,用 org.springframework.http.HttpStatus 表示。
- methods: 應該重試的HTTP方法,用 org.springframework.http.HttpMethod 來表示。
- series: 要重試的狀態代碼系列,用 org.springframework.http.HttpStatus.Series 表示。
- exceptions: 拋出的異常的列表,應該重試。
- backoff: 為重試配置的指數式backoff。重試是在 backoff 間隔 firstBackoff * (factor ^ n) 之后進行的,其中 n 是迭代次數。如果配置了 maxBackoff,應用的最大 backoff 時間被限制在 maxBackoff。如果 basedOnPreviousValue 為 true,則通過使用 prevBackoff * factor 來計算backoff。
如果啟用,為 Retry filter 配置的默認值如下。
- retries: 三次
- series: 5XX系列
- methods: GET 請求
- exceptions: IOException 和 TimeoutException
- backoff: disabled
下面配置了一個 Retry GatewayFilter。
Example 59. application.yml
spring:cloud:gateway:routes:- id: retry_testuri: http://localhost:8080/flakeypredicates:- Host=*.retry.comfilters:- name: Retryargs:retries: 3statuses: BAD_GATEWAYmethods: GET,POSTbackoff:firstBackoff: 10msmaxBackoff: 50msfactor: 2basedOnPreviousValue: false
當使用帶有 forward: 前綴的URL的 retry filter 時,應仔細編寫目標端點,以便在出現錯誤時,它不會做任何可能導致響應被發送到客戶端并提交的事情。例如,如果目標端點是一個 @Controller,目標controller方法不應該返回帶有錯誤狀態碼的 ResponseEntity。相反,它應該拋出一個 Exception 或發出一個錯誤信號(例如,通過 Mono.error(ex) 返回值),retry filter 可以被配置為通過重試來處理。 |
當對任何帶有body的HTTP方法使用 retry filter 時,body將被緩存,網關將變得內存受限。body被緩存在 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 定義的請求屬性(request attribute)中。該對象的類型是 org.springframework.core.io.buffer.DataBuffer。 |
一個簡化的 "快捷" 方式可以用一個 status 和 method 來添加。
以下兩個例子是等同的。
Example 60. application.yml
spring:cloud:gateway:routes:- id: retry_routeuri: https://example.orgfilters:- name: Retryargs:retries: 3statuses: INTERNAL_SERVER_ERRORmethods: GETbackoff:firstBackoff: 10msmaxBackoff: 50msfactor: 2basedOnPreviousValue: false- id: retryshortcut_routeuri: https://example.orgfilters:- Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false
6.34.RequestSize
當請求的大小超過允許的限制時,RequestSize GatewayFilter 工廠可以限制請求到達下游服務。該過濾器需要一個 maxSize 參數。maxSize 是一個 DataSize 類型,所以值可以定義為一個數字,后面有一個可選的 DataUnit 后綴,如 'KB' 或’MB'。默認是 'B',表示字節。它是以字節為單位定義的請求的可允許的大小限制。下面的列表配置了一個 RequestSize GatewayFilter。
Example 61. application.yml
spring:cloud:gateway:routes:- id: request_size_routeuri: http://localhost:8080/uploadpredicates:- Path=/uploadfilters:- name: RequestSizeargs:maxSize: 5000000
RequestSize GatewayFilter 工廠將響應狀態設置為 413 Payload Too Large,當請求由于大小而被拒絕時,會有一個額外的頭 errorMessage。下面的例子顯示了這樣一個 errorMessage。
errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
如果在路由定義中沒有提供filter參數,默認請求大小被設置為5MB。?
6.35.SetRequestHostHeader
在某些情況下,host 頭可能需要被重寫。在這種情況下,SetRequestHostHeader GatewayFilter 工廠可以將現有的 host header 替換成指定的值。該過濾器需要一個 host 參數。下面的列表配置了一個 SetRequestHostHeader GatewayFilter。
Example 62. application.yml
spring:cloud:gateway:routes:- id: set_request_host_header_routeuri: http://localhost:8080/headerspredicates:- Path=/headersfilters:- name: SetRequestHostHeaderargs:host: example.org
SetRequestHostHeader GatewayFilter 工廠將 host 頭的值替換為 example.org。
6.36.TokenRelay
Token Relay是指OAuth2消費者作為客戶端,將傳入的令牌轉發給傳出的資源請求。消費者可以是一個純粹的客戶端(如SSO應用程序)或一個資源服務器。
Spring Cloud Gateway 可以將 OAuth2 訪問令牌轉發到它所代理的服務的下游。為了在網關中添加這一功能,你需要像這樣添加 TokenRelayGatewayFilterFactory。
App.java
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("resource", r -> r.path("/resource").filters(f -> f.tokenRelay()).uri("http://localhost:9000")).build();
}
或者,這樣。
application.yaml
spring:cloud:gateway:routes:- id: resourceuri: http://localhost:9000predicates:- Path=/resourcefilters:- TokenRelay=
它將(除了登錄用戶和抓取令牌之外)把認證令牌傳遞給下游的服務(在這里是 /resource)。
要為 Spring Cloud Gateway 啟用這個功能,需要添加以下依賴
- org.springframework.boot:spring-boot-starter-oauth2-client
它是如何工作的? {githubmaster}/src/main/java/org/springframework/cloud/gateway/security/TokenRelayGatewayFilterFactory.java[filter]從當前認證的用戶中提取一個訪問令牌,并將其放在下游請求的請求頭中。
完整的工作樣本見 該項目。
只有當適當的 spring.security.oauth2.client.* 屬性被設置時, TokenRelayGatewayFilterFactory Bean才會被創建,這將觸發 ReactiveClientRegistrationRepository Bean的創建。
TokenRelayGatewayFilterFactory 使用的 ReactiveOAuth2AuthorizedClientService 的默認實現使用了一個內存數據存儲。如果你需要一個更強大的解決方案,你將需要提供你自己的實現 ReactiveOAuth2AuthorizedClientService。?
6.37. 默認 Filter
要添加一個filter并將其應用于所有路由,可以使用 spring.cloud.gateway.default-filters。這個屬性需要一個filter的列表。下面的列表定義了一組默認filter。
Example 63. application.yml
spring:cloud:gateway:default-filters:- AddResponseHeader=X-Response-Default-Red, Default-Blue- PrefixPath=/httpbin