【转】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

  如果你想为所有路由添加过滤器,可使用该属性。

 

posted @   闲人鹤  阅读(1580)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示