Spring Cloud Gateway网关之自定义路由过滤器

API网关
01 Spring Cloud Gateway网关之快速上手
02 Spring Cloud Gateway网关之两种路由配置方式
03 Spring Cloud Gateway网关之跨域支持
04 Spring Cloud Gateway网关之自定义全局过滤器
05 Spring Cloud Gateway网关之自定义路由过滤器
06 Spring Cloud Gateway网关之自定义路由谓词工厂
07 Spring Cloud Gateway网关之超时时间配置
08 Spring Cloud Gateway网关之配置说明
09 Zuul网关之快速上手
10 Zuul网关之路由配置
11 Zuul网关之跨域支持
12 Zuul网关之自定义过滤器
13 Zuul网关之超时时间配置

一 路由过滤器(GatewayFilter)

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器主要是作用于特定路由。 Spring Cloud Gateway包括许多内置的GatewayFilter工厂,每一个工厂都是一个路由过滤器。

二框架已实现的路由过滤器

要自定义路由过滤器,我们更多的会去参考gateway已帮我定义好的一些过滤器,了解其中的原理和实现方式,如果官方定义的无法满足我们的要求,我们才会考虑去自定义。

  • AddRequestHeader GatewayFilterFactory

    增加请求头的路由过滤器,主要接收namevalue两个参数,用法参考以下官网示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    spring:
    cloud:
    gateway:
    routes:
    - id: add_request_header_route
    uri: https://example.org
    filters:
    # 增加请求头 X-Request-red:blue
    - AddRequestHeader=X-Request-red, blue

    - id: add_request_header_route2
    uri: https://example.org
    predicates:
    - Path=/red/{segment}
    filters:
    # 增加请求头 url变量可以在value中引用 如下
    - AddRequestHeader=X-Request-Red, Blue-{segment}
  • AddRequestParameter GatewayFilterFactory

    增加请求参数,主要接收namevalue两个参数,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    spring:
    cloud:
    gateway:
    routes:
    - id: add_request_parameter_route
    uri: https://example.org
    filters:
    # 增加请求参数
    - AddRequestParameter=red, blue
    - id: add_request_parameter_route2
    uri: https://example.org
    predicates:
    - Host: {segment}.myhost.org
    filters:
    # 增加请求参数 url变量可以在value中引用 如下
    - AddRequestParameter=foo, bar-{segment}
  • AddResponseHeader GatewayFilterFactory

    增加响应头,主要接收namevalue两个参数,用法参考AddRequestParameter

  • DedupeResponseHeader GatewayFilterFactory

    去重响应头,主要接收name和另一个可选参数strategy。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    spring:
    cloud:
    gateway:
    routes:
    - id: dedupe_response_header_route
    uri: https://example.org
    filters:
    # 去重以下响应头
    - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

    DedupeResponseHeader过滤器还接受可选的策略参数strategy。值包含RETAIN_FIRST(默认值),RETAIN_LAST和RETAIN_UNIQUE。

    RETAIN_FIRST(默认值):保留第一个

    RETAIN_LAST:保留最后一个

    RETAIN_UNIQUE:仅保留唯一性 不相同的值都会保留

  • Hystrix GatewayFilterFactory

    由于Netflix的Hystrix已经不再更新。所以建议将Spring Cloud CircuitBreaker网关过滤器与Resilience4J一起使用,因为Spring Cloud Gateway将来的版本中将不再支持Hystrix。

    Hystrix熔断支持的过滤器。Hystrix是Netflix的一个库,用于实现断路器模式。 Hystrix GatewayFilter将断路器引入网关路由,保护服务免受级联故障的影响,并在下游故障的情况下提供后备响应。

    要在项目中启用Hystrix GatewayFilter实例,请添加对Spring Cloud Netflix的spring-cloud-starter-netflix-hystrix的依赖。

    该过滤器工厂主要接收name单个参数,即HystrixCommand的名称。如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    cloud:
    gateway:
    routes:
    - id: hystrix_route
    uri: https://example.org
    filters:
    - Hystrix=myCommandName

    hystrix.command.myCommandName.execution.isolation.thread.timeoutInMilliseconds: 5000

    Hystrix过滤器还可以接收可选的fallbackUri参数。当前,仅支持forward:schema的URI。如果调用了fallback,则请求将转发到与URI匹配的控制器,forward即可以是网关的controller也可以是转发到其他路由。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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
  • SpringCloudCircuitBreakerFilterFactory

    SpringCloudCircuitBreakerFilterFactory使用Spring Cloud CircuitBreaker API将网关路由包装在断路器中。 Spring Cloud CircuitBreaker支持可与Spring Cloud Gateway一起使用的两个库HystrixResilience4J。由于Netflix已将Hystrix置于仅维护模式,因此建议使用Resilience4J

    要启用Spring Cloud CircuitBreaker过滤器,您需要在类路径上放置spring-cloud-starter-circuitbreaker-reactor-resilience4j或spring-cloud-starter-netflix-hystrix。以下示例配置了一个Spring Cloud CircuitBreaker GatewayFilter:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: circuitbreaker_route
    uri: https://example.org
    filters:
    - CircuitBreaker=myCircuitBreaker

    要配置断路器,请参阅所使用的基础断路器实现的配置。

    Resilience4J 文档

    Hystrix 文档

    Spring Cloud CircuitBreaker过滤器还可以接受可选的fallbackUri参数。当前,仅支持forward:schema的URI。如果调用了fallback,则请求将转发到与URI匹配的控制器。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    spring:
    cloud:
    gateway:
    routes:
    - id: circuitbreaker_route
    uri: lb://backing-service:8088
    predicates:
    - Path=/consumingServiceEndpoint
    filters:
    - name: CircuitBreaker
    args:
    name: myCircuitBreaker
    fallbackUri: forward:/inCaseOfFailureUseThis
    - RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

    根据http状态触发熔断。

    在某些情况下,您可能想根据断路器包装的路线返回的状态代码来使断路器熔断。断路器配置对象获取状态码列表,如果返回该状态码,则会导致断路器跳闸。设置要使断路器跳闸的状态码时,可以使用带状态码值的整数或HttpStatus枚举的String表示形式,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    spring:
    cloud:
    gateway:
    routes:
    - id: circuitbreaker_route
    uri: lb://backing-service:8088
    predicates:
    - Path=/consumingServiceEndpoint
    filters:
    - name: CircuitBreaker
    args:
    name: myCircuitBreaker
    fallbackUri: forward:/inCaseOfFailureUseThis
    statusCodes:
    - 500
    - "NOT_FOUND"
  • FallbackHeaders GatewayFilterFactory

    FallbackHeadersGatewayFilterFactory允许在转发到外部应用中的fallbackUri的请求的请求头中添加Hystrix或Spring Cloud CircuitBreaker执行异常详细信息,如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    spring:
    cloud:
    gateway:
    routes:
    - id: ingredients
    uri: lb://ingredients
    predicates:
    - Path=//ingredients/**
    filters:
    - name: CircuitBreaker
    args:
    name: fetchIngredients
    fallbackUri: forward:/fallback
    - id: ingredients-fallback
    uri: http://localhost:9994
    predicates:
    - Path=/fallback
    filters:
    - name: FallbackHeaders
    args:
    executionExceptionTypeHeaderName: Test-Header

    在此示例中,在运行断路器时发生执行异常之后,该请求将转发到fallback端点或处理程序localhost:9994。 FallbackHeaders筛选器将具有异常类型,消息和(如果有)根本原因异常类型和消息的标头添加到该请求。

    您可以通过设置以下参数的值(以其默认值显示)来覆盖配置中标头的名称:

    • executionExceptionTypeHeaderName ("Execution-Exception-Type")
    • executionExceptionMessageHeaderName ("Execution-Exception-Message")
    • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")
    • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")
  • MapRequestHeader GatewayFilterFactory

    MapRequestHeaderGatewayFilterFactory接收fromHeader和toHeader参数,它创建一个新的请求头(toHeader),并从传入的HTTP请求中一个现有的请求头(fromHeader)中提取值。如果输入请求头不存在,则过滤器不起作用。如果新请求头已经存在,则其值将使用新值进行扩充。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: map_request_header_route
    uri: https://example.org
    filters:
    - MapRequestHeader=Blue, X-Request-Red

    这会将X-Request-Red:<values>请求头添加到下游请求中,并带有来自传入HTTP请求的Blue请求头的更新值。

  • PrefixPath GatewayFilterFactory

    PrefixPathGatewayFilterFactory使用单个参数prefix,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: prefixpath_route
    uri: https://example.org
    filters:
    - PrefixPath=/mypath

    这会将/mypath作为所有匹配请求的路径的前缀。因此,对/hello的请求将发送到/mypath/hello

  • PreserveHostHeader GatewayFilterFactory

    PreserveHostHeaderGatewayFilterFactory没有参数。此过滤器设置请求属性,路由过滤器将检查该请求属性,以确定是否应发送原始host请求头,而不是由HTTP客户端确定的host请求头。默认情况下,转发到下游时,host请求头会被remove掉,如果需要保留,则使用该过滤器。

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: preserve_host_route
    uri: https://example.org
    filters:
    - PreserveHostHeader
  • RequestRateLimiter GatewayFilterFactory

    请求限流过滤器,使用RateLimiter实现来确定是否允许继续当前请求。如果不是,则返回HTTP 429-太多请求(默认)的状态。

    该过滤器采用可选的keyResolver参数和特定于速率限制器的参数,keyResolver是一个实现KeyResolver接口的bean。在配置中,使用SpEL按名称引用bean。 #{@myKeyResolver}是一个SpEL表达式,它引用一个名为myKeyResolver的bean。接口如下:

    1
    2
    3
    4
    > public interface KeyResolver {
    > Mono<String> resolve(ServerWebExchange exchange);
    > }
    >

    KeyResolver接口允许可插拔策略派生用于限制请求的密钥。在未来的里程碑版本中,将有一些KeyResolver实现。

    KeyResolver的默认实现是PrincipalNameKeyResolver,它从ServerWebExchange检索Principal并调用Principal.getName()。

    默认情况下,如果KeyResolver找不到密钥,则拒绝请求。您可以通过设置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(正确或错误)和spring.cloud.gateway.filter.request-rate-limiter.empty-key来调整此行为。状态代码属性。

    无法使用“快捷方式”配置RequestRateLimiter。下面的示例无效的:

    1
    2
    # INVALID SHORTCUT CONFIGURATION
    spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}

    RedisRateLimiter的实现基于Stripe完成的。它需要使用spring-boot-starter-data-redis-active Spring Boot启动器。

    使用的算法是 令牌桶算法.

    redis-rate-limiter.replenishRate属性是您希望用户每秒允许多少个请求,而没有任何丢弃的请求。这是令牌桶被填充的速率.

    redis-rate-limiter.burstCapacity属性是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求

    redis-rate-limiter.requestedTokens属性是一个请求要花费多少个令牌。这是每个请求从存储桶中获取的令牌数,默认为1

    通过在replenishRateburstCapacity中设置相同的值可以实现稳定的速率。通过将burstCapacity设置为高于replenishRate,可以允许临时突发。在这种情况下,由于两次连续的突发会导致请求丢弃(HTTP 429-太多请求),因此需要在两次突发之间允许有一定的时间限制(根据replenishRate)。以下配置了redis-rate-limiter:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    > 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
    > redis-rate-limiter.requestedTokens: 1
    >

    这定义了每个用户10的请求速率限制。允许突发20,但是在下一秒中,仅10个请求可用。 KeyResolver是获取用户请求参数的简单方法(请注意,不建议在生产环境中使用此参数)。

    您还可以将速率限制器定义为实现RateLimiter接口的Bean。在配置中,可以使用SpEL按名称引用Bean。 #{@ myRateLimiter}是一个SpEL表达式,它引用名为myRateLimiter的bean。以下清单定义了一个速率限制器,该限制器使用前面清单中定义的KeyResolver:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    > spring:
    > cloud:
    > gateway:
    > routes:
    > - id: requestratelimiter_route
    > uri: https://example.org
    > filters:
    > - name: RequestRateLimiter
    > args:
    > rate-limiter: "#{@myRateLimiter}"
    > key-resolver: "#{@userKeyResolver}"
    >
  • RedirectTo GatewayFilterFactory

    RedirectToGatewayFilterFactory接收两个参数,即statusurlstatus参数应该是300系列重定向HTTP代码,例如301url参数应该是有效的URL。这是Location请求头的值。对于相对重定向,您应该使用uri:no://op作为路由定义的uri。下面的示例配置一个RedirectTo GatewayFilter:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: prefixpath_route
    uri: https://example.org
    filters:
    - RedirectTo=302, https://acme.org
  • RemoveRequestHeader GatewayFilterFactory

    RemoveRequestHeaderGatewayFilterFactory顾名思义,去掉响应头。接收一个name参数。如

    1
    2
    > - RemoveResponseHeader=X-Response-Foo
    >

    要删除任何类型的敏感标头,应为可能要执行此操作的任何路由配置此过滤器。此外,可以使用spring.cloud.gateway.default-filters一次配置此过滤器,并将其应用于所有路由。

  • RemoveRequestParameter GatewayFilterFactory

    RemoveRequestParameterGatewayFilterFactory去除请求参数,接收一个name参数。如:

    1
    2
    > - RemoveRequestParameter=red
    >
  • RewritePath GatewayFilterFactory

    该过滤器负责重写path,接收路径的 regexp 参数和 replacement 参数。这使用Java正则表达式提供了一种灵活的方式来重写请求路径。在实际使用中会经常用到。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    cloud:
    gateway:
    routes:
    - id: rewritepath_route
    uri: https://example.org
    predicates:
    - Path=/red/**
    filters:
    - RewritePath=/red(?<segment>/?.*), $\{segment}
  • RewriteLocationResponseHeader GatewayFilterFactory

    该过滤器主要重写Location响应头,通常摆脱特定于后端的细节。它接收stripVersionModelocationHeaderNamehostValueprotocolRegex参数。如:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    cloud:
    gateway:
    routes:
    - id: rewritelocationresponseheader_route
    uri: http://example.org
    filters:
    - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

    例如, 对于一个请求 POST api.example.com/some/object/name, object-service.prod.example.net/v2/some/object/idLocation 响应头 ,会被修改为 api.example.com/some/object/id.

    stripVersionMode参数具有以下可能的值:NEVER_STRIPAS_IN_REQUEST(默认值)和ALWAYS_STRIP

    • NEVER_STRIP:即使原始请求路径不包含任何版本,也不会剥离该版本
    • AS_IN_REQUEST:仅当原始请求路径不包含任何版本时,才剥离该版本。
    • ALWAYS_STRIP:即使原始请求路径包含版本,也始终剥离版本。

    hostValue参数(如果提供)用于替换Location响应头的host:port部分。如果未提供,则使用Host请求头的值。

    protocolRegex参数必须是有效的正则表达式字符串,协议名称与之匹配。如果不匹配,则过滤器不执行任何操作。默认值为http|https|ftp|ftps

  • RewriteResponseHeader GatewayFilterFactory

    该过滤器的作用是重新响应头,接收name, regexp, 和 replacement三个参数。如:

    1
    2
    > - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***
    >

    对于一个响应头的header值 /42?user=ford&password=omg!what&flag=true, 会被重写为 /42?user=ford&password=***&flag=true

  • SaveSession GatewayFilterFactory

    SaveSessionGatewayFilterFactory是保存会话状态的过滤器factory,在向下游转发之前保存。特别是对于像 Spring Session 这种懒加载数据存储是需要确保保存会话状态的。

    如果您将Spring Security与Spring Session集成在一起,并希望确保信息安全的转发到远程进程,那么这一点至关重要。

    配置方式:

    1
    2
    > - SaveSession
    >
  • SecureHeaders GatewayFilterFactory

    参考这篇博文的建议,该过滤器会在响应中添加一些安全相关的响应头。

    主要添加了以下响应头:

    • 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
    • x-frame-options
    • x-content-type-options
    • referrer-policy
    • content-security-policy
    • x-download-options
    • x-permitted-cross-domain-policies

    要禁用默认值,请设置spring.cloud.gateway.filter.secure-headers.disable属性,并用逗号分隔值。以下示例显示了如何执行此操作:

    1
    2
    > spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security
    >
  • SetPath GatewayFilterFactory

    SetPathGatewayFilterFactory接收一个template参数,如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    cloud:
    gateway:
    routes:
    - id: setpath_route
    uri: https://example.org
    predicates:
    - Path=/red/{segment}
    filters:
    - SetPath=/{segment}

    以上示例 ,如请求${GATEWAY_PATH}/red/abc会设置为/abc转发到下游。

  • SetRequestHeader GatewayFilterFactory

    设置请求头,接收namevalue参数,如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    spring:
    cloud:
    gateway:
    routes:
    - id: setrequestheader_route
    uri: https://example.org
    filters:
    - SetRequestHeader=X-Request-Red, Blue
    - id: setrequestheader_route2
    uri: https://example.org
    predicates:
    - Host: {segment}.myhost.org
    filters:
    - SetRequestHeader=foo, bar-{segment}
  • SetResponseHeader GatewayFilterFactory

    设置响应头,接收namevalue两个参数,如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    spring:
    cloud:
    gateway:
    routes:
    - id: setresponseheader_route
    uri: https://example.org
    filters:
    - SetResponseHeader=X-Response-Red, Blue
    - id: setresponseheader_route2
    uri: https://example.org
    predicates:
    - Host: {segment}.myhost.org
    filters:
    - SetResponseHeader=foo, bar-{segment}
  • SetStatus GatewayFilterFactory

    SetStatusGatewayFilterFactory 接收单个参数status。必须是SpringHttpStatus中的值,既可以是数字如404,也可以是枚举值如NOT_FOUND。如下示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    spring:
    cloud:
    gateway:
    routes:
    - id: setstatusstring_route
    uri: https://example.org
    filters:
    - SetStatus=BAD_REQUEST
    - id: setstatusint_route
    uri: https://example.org
    filters:
    - SetStatus=401

    可以通过以下配置将原状态值附带到响应头中

    1
    2
    3
    4
    5
    6
    > spring:
    > cloud:
    > gateway:
    > set-status:
    > original-status-header-name: original-http-status
    >
  • StripPrefix GatewayFilterFactory

    StripPrefixGatewayFilterFactory是用来重写path的,主要功能:设置跳过前缀节数,接收一个参数parts,该值是一个数字即转发到下游时需要跳过的path前缀节数。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    cloud:
    gateway:
    routes:
    - id: nameRoot
    uri: https://nameservice
    predicates:
    - Path=/v1/name/**
    filters:
    - StripPrefix=2

    以上示例,当网关请求是${gatewayUrl}/v1/name/zhangsan会被跳过2节变成/zhangsan转发下游服务。

  • Retry GatewayFilterFactory

    RetryGatewayFilterFactory是重试过滤器,支持以下参数:

    • retries: 应尝试的重试次数。
    • statuses: 应重试的HTTP状态代码,值参考org.springframework.http.HttpStatus.
    • methods: 应重试的Http methods,值参考 org.springframework.http.HttpMethod.
    • series: 要重试的状态码系列, 值参考 org.springframework.http.HttpStatus.Series.
    • exceptions: 应重试的异常。
    • backoff: 重试配置的指数补偿。在firstBackoff * (factor ^ n)的退避间隔后执行重试,其中n是迭代。如果配置了maxBackoff,则将应用的最大退避限制为maxBackoff。如果basedOnPreviousValue为true,则使用prevBackoff * factor计算退避量。

    如果启用了以下默认值,则为“重试”筛选器配置:

    • retries: 3次
    • series: 5XX状态码系列
    • methods: GET method
    • exceptions: IOException and TimeoutException
    • backoff: disabled

    配置示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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
    methods: GET,POST
    backoff:
    firstBackoff: 10ms
    maxBackoff: 50ms
    factor: 2
    basedOnPreviousValue: false
  • RequestSize GatewayFilterFactory

    请求大小过滤器,过滤器接收 maxSize 参数。

    maxSize是一种DataSize类型,因此可以将值定义为一个数字,后跟一个可选的DataUnit后缀,例如'KB''M'。字节的默认值为'B'。它是请求的允许大小限制,以字节为单位。以下配置了RequestSize GatewayFilter:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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,并带有附加报头errorMessage。以下示例显示了这样的错误消息。

    1
    2
    > errorMessage` : `Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
    >
    如果未在路由定义中作为过滤器参数提供,则默认请求大小将设置为5 MB。
  • SetRequestHostHeader GatewayFilterFactory

    设置Host请求头,在某些情况下,可能需要覆盖Host请求头。示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    spring:
    cloud:
    gateway:
    routes:
    - id: set_request_host_header_route
    uri: http://localhost:8080/headers
    predicates:
    - Path=/headers
    filters:
    - name: SetRequestHost
    args:
    host: example.org
  • ModifyRequestBody GatewayFilterFactory

    修改请求body,只能使用Java DSL来配置此过滤器。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @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;
    }
    }
  • ModifyResponseBody GatewayFilterFactory

    重写响应body,只能使用Java DSL来配置此过滤器。如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @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();
    }

三 让过滤器在全局生效

要添加过滤器并将其应用于所有路由,可以使用spring.cloud.gateway.default-filters。此属性采用过滤器列表。以下清单定义了一组默认过滤器:

1
2
3
4
5
6
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin

四 自定义路由过滤器

通过了解框架自带的30多个路由过滤器,参考后可定义业务需要的路由过滤器。

  • 自定义过滤器工厂继承AbstractGatewayFilterFactory<Config>

    继承后重写apply方法如下,如果属性仅有namevalue的可直接继承AbstractNameValueGatewayFilterFactory,这样里面的Config也是可以复用的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Override
    public GatewayFilter apply(Config config) {
    return new GatewayFilter() {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange,
    GatewayFilterChain chain) {
    // ... 具体业务逻辑
    }

    @Override
    public String toString() {
    // 重写toString...
    }
    };
    }

    其中Config一般是自定义过滤器工厂的静态内部类,如果Config只有一个name属性可以复用父类AbstractGatewayFilterFactory中定义的静态内部类NameConfig,如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public static class Config {
    private String regexp;
    private String replacement;

    public String getRegexp() {
    return regexp;
    }
    public Config setRegexp(String regexp) {
    Assert.hasText(regexp, "regexp must have a value");
    this.regexp = regexp;
    return this;
    }
    public String getReplacement() {
    return replacement;
    }
    public Config setReplacement(String replacement) {
    Assert.notNull(replacement, "replacement must not be null");
    this.replacement = replacement;
    return this;
    }
    }

    其中Config里的属性就是过滤器接收的参数定义。

  • 重写过滤器工厂的shortcutFieldOrder方法定义快捷方式的字段顺序,如下:

    1
    2
    3
    4
    @Override
    public List<String> shortcutFieldOrder() {
    return Arrays.asList(REGEXP_KEY, REPLACEMENT_KEY);
    }
  • 重写过滤器工厂的name()方法可以自定义过滤器的名称,如果不重写,默认会使用工厂类的前缀(即GatewayFilterFactory之前的类名部分)作为过滤器名称。默认情况如:

    1
    RewritePathGatewayFilterFactory 的 过滤器名称 默认是 RewritePath

    重写示例如:

    1
    2
    3
    4
    @Override
    public String name() {
    return "CircuitBreaker";
    }
  • 如果需要关心自定义过滤器在过滤器联调中的顺序位置,则有以下两种方式:

    1 继承org.springframework.core.Ordered接口,实现getOrder,返回具体的order次序号,如果不设置,默认情况下,过滤器的顺序会从1开始按着Route中的定义依次排序。

    2 写Order注解

  • 最后,一个示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {

public PreGatewayFilterFactory() {
super(Config.class);
}

@Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
//If you want to build a "pre" filter you need to manipulate the
//request before calling chain.filter
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
//use builder to manipulate the request
return chain.filter(exchange.mutate().request(builder.build()).build());
};
}

public static class Config {
//Put the configuration properties for your filter here
}

}