Spring Cloud Gateway(译)(Part 2)

6. GatewayFilter 工厂

Route filters 允许以某种方式修改传入的 HTTP 请求或返回的 HTTP 响应. Route过滤器适用于特定路由. Spring Cloud Gateway包括许多内置的GatewayFilter 工厂.

有关如何使用以下任意过滤器的更多详细示例, 参考示例 unit tests.

6.1. The AddRequestHeader GatewayFilter Factory

AddRequestHeader GatewayFilter factory 有一个 namevalue 的键值对参数. 下面是一个 AddRequestHeader GatewayFilter 的配置示例:

Example 13. application.yml

spring:
 cloud:
   gateway:
     routes:
     - id: add_request_header_route
       uri: https://example.org
       filters:
       - AddRequestHeader=X-Request-red, blue

此配置将 X-Request-red:blue 请求头添加到所有匹配请求的下游请求头中.

AddRequestHeader 能够识别匹配的路径或主机的 URI 变量. URI 变量可以在运行时当作value值拓展使用. 下面的示例演示了如何在 AddRequestHeader GatewayFilter 使用变量:

Example 14. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - AddRequestHeader=X-Request-Red, Blue-{segment}

6.2. The AddRequestParameter GatewayFilter Factory

AddRequestParameter GatewayFilter 工厂有namevalue 键值对参数. 下面是 AddRequestParameter GatewayFilter 的配置示例:

Example 15. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue

这会将 red=blue 添加到所有匹配请求的下游请求的查询字符串中.

AddRequestParameter 能够识别匹配的路径或主机的 URI 变量. URI 变量可以在运行时当作value值拓展使用. 下面的示例演示了如何在 AddRequestParameter GatewayFilter 使用变量:

Example 16. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - AddRequestParameter=foo, bar-{segment}

6.3. The AddResponseHeader GatewayFilter Factory

AddResponseHeader GatewayFilter工厂有namevalue 键值对参数. 下面是 AddResponseHeader GatewayFilter 配置示例:

Example 17. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue

此配置将 X-Response-Foo:Bar 响应头添加到所有匹配请求的下游响应头中.

AddResponseHeader 能够识别匹配的路径或主机的 URI 变量. URI 变量可以在运行时当作value值拓展使用. 下面的示例演示了如何在 AddResponseHeader GatewayFilter 使用变量:

Example 18. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - AddResponseHeader=foo, bar-{segment}

6.4. The DedupeResponseHeader GatewayFilter Factory

DedupeResponseHeader GatewayFilter 工厂包含一个name 参数和一个 strategy 可选参数. name c以包含以空格分隔的 header names 列表. 下面是DedupeResponseHeader GatewayFilter 配置示例:

Example 19. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: dedupe_response_header_route
        uri: https://example.org
        filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

在网关CORS逻辑和下游逻辑都将它们添加的情况下,这将删除 Access-Control-Allow-Credentials and Access-Control-Allow-Origin 响应头的重复值.

DedupeResponseHeader 过滤器还接受可选的 strategy 策略参数. 接收的值为RETAIN_FIRST (default), RETAIN_LAST, 和RETAIN_UNIQUE.

6.5. The Hystrix GatewayFilter Factory

Netflix has put Hystrix in maintenance mode. 我们建议你将 Spring Cloud CircuitBreaker Gateway Filter 和 Resilience4J 一起使用, 因为在将来的版本中将不再支持Hystrix.

Hystrix 是 Netflix 的一个库,用来实现 circuit breaker pattern (断路器模式). Hystrix GatewayFilter 使你可以将断路器引入网关路由, 保护你的应用免受级联故障的影响,并在下游故障发生时,提供fallback 响应.

如果想要在你的项目中启用 Hystrix GatewayFilter , 请添加 对Spring Cloud Netflixspring-cloud-starter-netflix-hystrix 的依赖.

Hystrix GatewayFilter 工厂仅需要一个 name 参数, 即HystrixCommand的名称. 下面是 Hystrix GatewayFilter 配置示例:

Example 20. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: https://example.org
        filters:
        - Hystrix=myCommandName

将使用 myCommandName作为名称生成 HystrixCommand 对象来进行熔断管理 .

Hystrix 过滤器还可以接受可选的fallbackUri 参数. 当前, 仅仅支持这种转发的 forward: schemed URIs . 如果fallback被调用, 请求将会被转发到与URI匹配的 controller 中. 下面的示例配置了一个 fallback:

Example 21. application.yml

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 fallback被调用时,它将转发到 /incaseoffailureusethis URI . 请注意,该示例还演示了 (可选) Spring Cloud Netflix Ribbon load-balancing (在目标UR前加了 lb 前缀).

该示例主要方案是将 fallbackUri 指向网关内部的 controller 或 handler . 但是, 你也可以将请求重新路由到外部应用的的 controller 或 handler 中, 如下所示:

Example 22. application.yml

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

在此示例中, 网关中没有 fallback endpoint 或 handler. 但是, 在另一个应用中却有一个, 注册地址为localhost:9994.

即使将请求转发给了 fallback, Hystrix Gateway filter 依旧会提供提供造成该原因的 Throwable . 它作为 ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR 属性添加到ServerWebExchange 中, 您可以在网关应用程序中处理fallback时使用该属性.

对于外部controller/handler 解决方案,你可以添加带有异常详细信息的headers .更多详情,请参考FallbackHeaders GatewayFilter Factory section.

你可以设置Hystrix 配置(例如超时),无论是全局配置还是逐条路由配置,更多信息,请参考 Hystrix wiki.

若想为上面的例路由设置五秒钟的超时时间,可以使用以下配置:

Example 23. application.yml

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

6.6. Spring Cloud CircuitBreaker GatewayFilter Factory

Spring Cloud CircuitBreaker GatewayFilter工厂使用Spring Cloud CircuitBreaker API将网关路由包装在断路器中。 在 Spring Cloud Gateway中, Spring Cloud CircuitBreaker支持两个库Hystrix和Resilience4J。 由于Netflix已将Hystrix置于仅维护模式,因此建议使用Resilience4J。

若要启用 Spring Cloud CircuitBreaker filter, 你需要将spring-cloud-starter-circuitbreaker-reactor-resilience4jspring-cloud-starter-netflix-hystrix 导入到你的 classpath 下. 下面是 Spring Cloud CircuitBreaker GatewayFilter 的配置示例:

Example 24. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: https://example.org
        filters:
        - CircuitBreaker=myCircuitBreaker

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

The Spring Cloud CircuitBreaker filter 过滤器还可以接受可选的fallbackUri 参数. 当前, 仅仅支持这种转发的 forward: schemed URIs . 如果fallback被调用, 请求将会被转发到与URI匹配的 controller 中. 下面的示例配置了一个 fallback:

Example 25. application.yml

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

上面的配置在java中也可以实现相同的功能:

Example 26. 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();
}

该示例演示了当 circuit breaker fallback被调用时,它将转发到 /inCaseofFailureUseThis URI . 请注意,该示例还演示了 (可选) Spring Cloud Netflix Ribbon load-balancing (在目标UR前加了 lb 前缀).

该示例主要方案是将 fallbackUri 指向网关内部的 controller 或 handler . 但是, 你也可以将请求重新路由到外部应用的的 controller 或 handler 中, 如下所示:

Example 22. application.yml

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

在此示例中, 网关中没有 fallback endpoint 或 handler. 但是, 在另一个应用中却有一个, 注册地址为localhost:9994.

如果将请求转发给fallback,同样,Spring Cloud CircuitBreaker网关过滤器也会提供引发该请求的Throwable . 它作为ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange,可在处理网关应用程序中的fallback 时使用。

对于外部controller/handler 的解决方案,可以添加带有异常详细信息的headers .下一章节我们会详细论述.

6.7. The FallbackHeaders GatewayFilter Factory

FallbackHeaders 工厂允许你在在转发到外部应用程序中的fallbackUri 的请求头中添加 Hystrix 或 Spring Cloud CircuitBreaker 执行异常详细信息, 如下所示:

Example 28. application.yml

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

在此示例中, 在运行断路器时发生执行异常之后, 该请求将转发到在运行在 localhost:9994 上的应用程序的fallback endpoint 或handler . FallbackHeaders filter将具有异常类型, 消息和(如果有) root cause exception 类型和消息添加到请求头中.

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

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

6.8. The MapRequestHeader GatewayFilter Factory

The MapRequestHeader GatewayFilter 工厂有两个参数 fromHeadertoHeader. 它创建一个新的 header (toHeader), 然后从传入的http请求中解析现有的(fromHeader) 的值.如果输入请求中的(fromHeader) 不存在, 则过滤器不起作用. 反之, 新的 header (toHeader)的值则设置为(fromHeader) 的值. 下面是 MapRequestHeader的配置示例:

Example 29. application.yml

Example 29. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: map_request_header_route
        uri: https://example.org
        filters:
        - MapRequestHeader=Blue, X-Request-Red

这会将 X-Request-Red:请求头添加到下游请求中,并赋值为传入HTTP请求的Blue header的值。

6.9. The PrefixPath GatewayFilter Factory

PrefixPath GatewayFilter 工厂只有一个 prefix 参数. 下面是 PrefixPath GatewayFilter的配置示例:

Example 30. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/mypath

这会将 /mypath 作为所有匹配请求的路径前缀. 所有访问 /hello 的请求都会被发送到/mypath/hello.

6.10. The PreserveHostHeader GatewayFilter Factory

PreserveHostHeader GatewayFilter 工厂没有参数. 该filter 设置请求属性,路由过滤器将检查该请求属性,以确定是否应发送原始host header,而不是由HTTP客户端确定的host header。. The following example configures a PreserveHostHeader GatewayFilter:

ServerWebExchange读取PRESERVE_HOST_HEADER_ATTRIBUTE属性,没有则默认false。如果为true,则proxyRequest.header(HttpHeaders.HOST, host),传递原始的host头部。

Example 31. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: https://example.org
        filters:
        - PreserveHostHeader

6.11. The RequestRateLimiter GatewayFilter Factory

RequestRateLimiter GatewayFilter工厂利用 RateLimiter 的实现来决定是否允许当前的请求继续被执行.如果不允许, 则返回状态码HTTP 429 - Too Many Requests (默认情况下).

该filter 接受一个可选的keyResolver 参数和特定于速率限制器的参数(本节后面将介绍).

keyResolver 是一个 KeyResolver 接口的实现类.在配置中, 使用 SpEL 按名称引用bean. #{@myKeyResolver} 是一个SpEL 表达式,它引用了名为 myKeyResolver的bean. 下面示例显示了 KeyResolver 接口:

Example 32. KeyResolver.java

Example 32. 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 or false) and spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 属性来改变它的行为.

RequestRateLimiter 无法使用 "简洁"符号配置. 下面的示例是无效的:

Example 33. application.properties

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

Redis的实现基于 Stripe 实现的. 它需要引入spring-boot-starter-data-redis-reactive Spring Boot starter.

它的算法实现是(令牌桶算法) Token Bucket Algorithm.

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

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

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

通过将 replenishRateburstCapacity设置为相同的值可以实现固定的速率. 通过设置 burstCapacity 的值高于replenishRate,可以应对临时突发状况. 在这种情况下, 速率限制器需要在两次突发之间保留一段时间 (根据 replenishRate), 因为两个连续的突发将导致请求丢弃 (HTTP 429 - Too Many Requests). 以下清单配置了 redis-rate-limiter:

如果想要速率限制为1 request/s,可以通过设置 replenishRate 为所需的请求数. 将requestedTokens 设置为以秒为单位的时间跨度并将burstCapacity 设置为 replenishRaterequestedTokens的乘积. 例如. 设置replenishRate=1,requestedTokens=60burstCapacity=60将导致限制为1 request/min`.

Example 34. application.yml

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

下面是用Java实现 KeyResolver 的示例:

Example 35. Config.java

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

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

你也可以通过实现 RateLimiter接口来定义一个速率限制器. 在配置中, 可以使用SpEL按名称引用bean. #{@myRateLimiter} 是一个SpEL表达式, 它引用名为 myRateLimiter的bean. 以下清单定义了一个速率限制器,该限制器使用上一个清单中定义的 KeyResolver :

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

6.12. The RedirectTo GatewayFilter Factory

RedirectTo GatewayFilter 工厂采用两个参数, 即statusurl. 参数 status 是300系列重定向的 HTTP 状态码, 例如 301. 参数 url 应该是一个有效 URL. 它会被 添加到此请求返回的消息中的Location header的值里. 对于相对路径重定向, 你应该使用 uri: no://op 作为路由定义的uri. 下面是RedirectTo GatewayFilter配置示例:

Example 37. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org

这将发送一个带有Location:https://acme.orgheader 的302状态码以执行重定向。

6.13. The RemoveRequestHeader GatewayFilter Factory

RemoveRequestHeader GatewayFilter 工厂接受一个name 的参数. 它是要删除的header的名称. 下面是RemoveRequestHeader GatewayFilter:配置示例

Example 38. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo

这会在将X-Request-Fooheader发送到下游之前将其删除。

6.14. RemoveResponseHeader GatewayFilter Factory

The RemoveResponseHeader GatewayFilter 工厂接受一个name 的参数. 它是要删除的header的名称. 下面是RemoveResponseHeader GatewayFilter配置示例:

Example 39. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: https://example.org
        filters:
        - RemoveResponseHeader=X-Response-Foo

这将从响应中删除 X-Response-Foo header,然后将其返回到网关客户端。

若要删除所有的敏感header, 你需要为所有的路由配置该filter. 另外, 你可以使用 spring.cloud.gateway.default-filters 只配置一次,并应用到所有的路由上.

6.15. The RemoveRequestParameter GatewayFilter Factory

RemoveRequestParameter GatewayFilter 工厂接受一个 name 参数. 它是要被删除的query 参数的名称. 下面是RemoveRequestParameter GatewayFilter配置示例:

Example 40. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestparameter_route
        uri: https://example.org
        filters:
        - RemoveRequestParameter=red

网关会在发送给下游之前将名为 red query parameter删除.

6.16. The RewritePath GatewayFilter Factory

RewritePath GatewayFilter 工厂接受一个 path regexp 参数和一个 replacement 参数. 采用了 Java regular 表达式提供了一种灵活的方式重写请求路径. 下面是RewritePath GatewayFilter的配置示例:

Example 41. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/foo/**
        filters:
        - RewritePath=/red(?<segment>/?.*), $\{segment}

对于请求路径 /red/blue, 在发送到下游之前,应将路径设置为 /blue . 注意,你需要将 $ 替换成 $\ , 因为这是 YAML 规范.

6.17. RewriteLocationResponseHeader GatewayFilter Factory

RewriteLocationResponseHeader GatewayFilter 工厂会修改 Location response header 的值, usually to get rid of backend-specific details. 它输入四个参数 stripVersionMode, locationHeaderName, hostValue, 和protocolsRegex . 下面是RewriteLocationResponseHeader GatewayFilter的配置示例:

Example 42. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: rewritelocationresponseheader_route
        uri: http://example.org
        filters:
        - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

如上所示, 一个 请求 POST api.example.com/some/object/name的 Locationresponse header 的值object-service.prod.example.net/v2/some/object/id 被重写为 api.example.com/some/object/id.

stripVersionMode 参数有三个可选值: NEVER_STRIP, AS_IN_REQUEST (default), and ALWAYS_STRIP.

  • NEVER_STRIP: 版本信息不会被剥离,即使原始请求路径不包含版本 .
  • AS_IN_REQUEST 仅当原始请求路径不包含任何版本时,才会剥离版本 [default].
  • ALWAYS_STRIP 即使原始请求路径包含版本,也会剥离版本 .

参数hostValue , 如果提供, 会替换response Location header值中的 host:port 部分.如果没有提供, 则会使用 request header的 Host 作为默认值.

参数protocolsRegex必须是一个有效的正则表达式字符串, 协议名称与之匹配. 如果不匹配, 该过滤器不起作用. 默认值是 http|https|ftp|ftps.

6.18. The RewriteResponseHeader GatewayFilter Factory

RewriteResponseHeader GatewayFilter 工厂接受三个参数 name, regexp, 和replacement .它使用Java正则表达式以灵活的方式重写response header value. 下面是RewriteResponseHeader GatewayFilter的配置示例:

Example 43. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: https://example.org
        filters:
        - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

如上所示,header 的X-Response-Red 原始值为/42?user=ford&password=omg!what&flag=true,当向下游发送请求后会被重置为 /42?user=ford&password=***&flag=true . 你必须使用 $\ 来替代 $ , 因为这是YAML 的规范.

6.19. The SaveSession GatewayFilter Factory

The SaveSession GatewayFilter 工厂会在想下游发出请求之前强制执行WebSession::save 操作. 对于使用例如 Spring Session 这类延迟数据存储的 ,确保你在向下游转发前保存session 状态时特别有用. 下面是SaveSession GatewayFilter配置示例:

Example 44. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: https://example.org
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession

如果你将 Spring Security 和Spring Session 集成使用 ,并确保安全性详细信息转发到远程进程, 那么这一点至关重要 .

6.20. The SecureHeaders GatewayFilter Factory

SecureHeaders GatewayFilter 工厂会为响应添加一些列的安全headers, 更多信息,请参考 this blog post.

添加了以下headers (显示其默认值) :

  • 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 属性,其值用逗号分隔. 下面的示例显示了如何禁用默认值:

spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security

必须使用安全标头的小写全名来禁用它..

6.21. The SetPath GatewayFilter Factory

SetPath GatewayFilter factory 接收一个 template 参数. 它提供了一种简单方法通过允许路径的segments来操作请求路径. 这使用了Spring Framework中的URI模板. 允许多个匹配segments . 下面是SetPath GatewayFilter配置示例:

Example 45. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - SetPath=/{segment}

对于 /red/blue的请求路径, 在发送给下游请求之前会将路径修改为 /blue .

6.22. The SetRequestHeader GatewayFilter Factory

SetRequestHeader GatewayFilter 工厂接收 namevalue 两个参数. 下面是SetRequestHeader GatewayFilter配置示例:

Example 46. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setrequestheader_route
        uri: https://example.org
        filters:
        - SetRequestHeader=X-Request-Red, Blue

GatewayFilter 用于给定名称的headers 替换值(而不是添加) . 因此 , 如果请求头为 X-Request-Red:1234, 则将其替换为X-Request-Red:Blue, 这是下游服务将收到的内容.

知道用于匹配路径或主机的URI变量。 URI变量可以在值中使用,并在运行时扩展。 以下示例配置使用变量的

SetRequestHeader能够识别用于匹配路由或主机的URL变量. URI 变量可以在运行时拓展,并赋值给value中的变量. 下面是SetRequestHeader GatewayFilter 使用变量的配置示例:

Example 47. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setrequestheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetRequestHeader=foo, bar-{segment}

6.23. The SetResponseHeader GatewayFilter Factory

SetResponseHeader GatewayFilter 工厂接收 namevalue 两个参数. 下面是SetResponseHeader GatewayFilter配置示例:

Example 48. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        filters:
        - SetResponseHeader=X-Response-Red, Blue

GatewayFilter 用于给定名称的headers 替换值(而不是添加) . 因此 , 如果请求头为 X-Request-Red:1234, 则将其替换为X-Request-Red:Blue, 这是gateway client 将收到的内容.

SetResponseHeader能够识别用于匹配路由或主机的URL变量. URI 变量可以在运行时拓展,并赋值给value中的变量. 下面是SetResponseHeader GatewayFilter 使用变量的配置示例:

Example 49. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetResponseHeader=foo, bar-{segment}

6.24. The SetStatus GatewayFilter Factory

SetStatus GatewayFilter 工厂接收一个参数 status. 它必须是有效的 Spring HttpStatus. 它可以是整数值 404 或枚举的字符串表示形式: NOT_FOUND. 下面是SetStatus GatewayFilter配置示例:

Example 50. application.yml

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

上面例子中,两种路由都会将响应的状态码设置为401.

你可以将 SetStatus GatewayFilter设置为响应的header 从代理请求返回原始的HTTP状态代码. 如果配置如下属性,则header将会添加到response中:

Example 51. application.yml

spring:
  cloud:
    gateway:
      set-status:
        original-status-header-name: original-http-status

6.25. The StripPrefix GatewayFilter Factory

StripPrefix GatewayFilter 工厂接收一个参数, 即parts. 参数 parts 的意思是在想下游发送请求之前,要从请求中剥离路径中的parts数量. 下面是 StripPrefix GatewayFilter的配置示例:

Example 52. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

当向网关发送 /name/blue/red请求时, 对nameservice 的请求则是nameservice/red.

6.26. The Retry GatewayFilter Factory

Retry GatewayFilter 工厂支持一下参数:

  • retries: 应尝试的重试次数.
  • statuses: 应该重试的HTTP 状态码, 用org.springframework.http.HttpStatus枚举值表示.
  • methods: 需要重试的HTTP请求方法 , 用 org.springframework.http.HttpMethod 枚举值表示.
  • series: 要重试的状态码系列, 用 org.springframework.http.HttpStatus.Series枚举值表示..
  • exceptions: 应重试的异常列表.
  • backoff: 重试配置的指数间隔. 重试在 firstBackoff * (factor ^ n)的窗口间隔之后执行, 其中n 是迭代. 如果maxBackoff 设置了值, 则应用的最大窗口间隔限制为maxBackoff. 如果 basedOnPreviousValue 设为 true, 则通过使用 prevBackoff * factor来计算窗口.

如果启用该filter,下面是 Retry filter的默认值,:

  • retries: 3次
  • series: 5XX 系列
  • methods: GET 方法
  • exceptions: IOExceptionTimeoutException
  • backoff: 不启用

下面是 Retry GatewayFilter的配置示例:

Example 53. application.yml

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

当 retry filter 和 forward: prefixed URL 结合使用的时候, 应仔细配置 target endpoint, 以便在发生错误的时候,它不会执行本应响应到客户端的的操作. 例如,如果 target endpoint 一个带注释的 controller, 目标 controller 方法不应该返回带有 error status code ResponseEntity . 相反, 它应该抛出 Exception 或错误信号 (例如, 通过Mono.error(ex) 返回值), 通过配置retry filter 来进行retrying处理.

当retry filter和任何具有body的HTTP方法一起使用时, body 将会被缓存, gateway应用受限于内存限制. body 缓存在ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR定义的请求属性中. 对象的类型是org.springframework.core.io.buffer.DataBuffer.

6.27. The RequestSize GatewayFilter Factory

当你想要限制request size的时候 RequestSize GatewayFilter 工厂可以限制request size超过限制大小的的请求发送到下游服务. 该filter 只有一个 maxSize 参数. 参数maxSize is a类型, 因此可以将值定义为一个数字, f后跟一个可选的 DataUnit 后缀, 例如 'KB' or 'MB'. 默认时是 'B' (即byte). 它是request size的允许size限制,以bytes为单位 . 下面是 RequestSize GatewayFilter的配置示例:

Example 54. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
        uri: http://localhost:8080/upload
        predicates:
        - Path=/upload
        filters:
        - name: RequestSize
          args:
            maxSize: 5000000

当请求因为太大而被拒绝时,RequestSize GatewayFilter 工厂设置response status 为413 Payload Too Large 并附加一个名为errorMessage的header. 下面的示例显示了errorMessage:

errorMessage` : `Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB

如果未在路由定义中RequestSize GatewayFilter,则默认请求大小将设置为5 MB.

6.28. Modify a Request Body GatewayFilter Factory

你可以使用 ModifyRequestBody filter 来修改Request body,然后将其发送到下游服务中.

该filter 只能通过 Java DSL来配置 .

下面显示了如何使用 GatewayFilter来修改Request body:

@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;
    }
}

6.29. Modify a Response Body GatewayFilter Factory

你可以使用 ModifyResponseBody filter 来修改 Response body 当网关返回到客户端之前.

该filter 只能通过 Java DSL来配置 .

下面的示例显示了如何通过GatewayFilter 来修改Response body :

@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();
}

6.30. Default Filters

若想为所有的路由配置filters ,你可以使用spring.cloud.gateway.default-filters. 此属性采用filters列表.下面示例定义了一组Default filters:

Example 55. application.yml

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容