【轉】Spring Cloud Gateway-過濾器工廠詳解(GatewayFilter Factories)


本文分享自微信公眾號 - IT牧場(itmuch_com),作者:itmuch

 

本文基於 Spring Cloud Greenwich SR2 ,理論支持 Spring Cloud Greenwich SR1 ,其中的新特性標注出來了。

本文探討Spring Cloud Gateway內置的Filter工廠,這些內置工廠類都集成了抽象類:AbstractGatewayFilterFactory,具體內置Filter包括:

AddRequestHeader GatewayFilter Factory
AddRequestParameter GatewayFilter Factory
AddResponseHeader GatewayFilter Factory
DedupeResponseHeader GatewayFilter Factory
Hystrix GatewayFilter Factory
FallbackHeaders GatewayFilter Factory
PrefixPath GatewayFilter Factory
PreserveHostHeader GatewayFilter Factory
RequestRateLimiter GatewayFilter Factory
RedirectTo GatewayFilter Factory
RemoveHopByHopHeadersFilter GatewayFilter Factory
RemoveRequestHeader GatewayFilter Factory
RemoveResponseHeader GatewayFilter Factory
RewritePath GatewayFilter Factory
RewriteResponseHeader GatewayFilter Factory
SaveSession GatewayFilter Factory
SecureHeaders GatewayFilter Factory
SetPath GatewayFilter Factory
SetResponseHeader GatewayFilter Factory
SetStatus GatewayFilter Factory
StripPrefix GatewayFilter Factory
Retry GatewayFilter Factory
RequestSize GatewayFilter Factory
Modify Request Body GatewayFilter Factory
Modify Response Body GatewayFilter Factory
Default Filters

在Spring Cloud Greenwich SR1中,以上的內置的Filter有些是不存在的,如果你正好需要這個工程,可以人工把SR2的Filter復制過來,放到自己的項目里。

 

技巧

  1. 斷點打在 org.springframework.cloud.gateway.filter.NettyRoutingFilter#filter ,就可以調試Gateway轉發的具體細節了。

  2. 添加如下配置,可觀察到一些請求細節:

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

  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重復了,這種情況有些Web請求會報異常:Cross-Origin Resource Sharing error: MultiptleAllowOriginValues 

  要想把這兩個Header去重,只需設置成如下即可。

filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

  也就是說,想要去重的Header如果有多個,用空格分隔即可;去重策略:

RETAIN_FIRST: 默認值,保留第一個值
RETAIN_LAST: 保留最后一個值
RETAIN_UNIQUE: 保留所有唯一值,以它們第一次出現的順序保留

 

5 Hystrix GatewayFilter Factory

  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

  也是對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

   在視頻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[1] 組織規定的。

  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

  修改響應的狀態碼,值可以是數字,也可以是字符串。但一定要是Spring HttpStatus 枚舉類中的值。如上配置,兩種方式都可以返回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

   該過濾器處於 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

   該過濾器處於 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

  如果你想為所有路由添加過濾器,可使用該屬性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM