115. GatewayFilter Factories
路由filter允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由filter适用于特定路由。 Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。
注意有关如何使用以下任何filter的更多详细示例,请查看unit tests。
115.1 AddRequestHeader GatewayFilter 工厂
AddRequestHeader GatewayFilter 工厂采用名称和值参数。
application.yml.
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
这会将X-Request-Foo:Bar
Headers 添加到所有匹配请求的下游请求 Headers 中。
115.2 AddRequestParameter GatewayFilter 工厂
AddRequestParameter GatewayFilter 工厂采用名称和值参数。
application.yml.
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://example.org
filters:
- AddRequestParameter=foo, bar
对于所有匹配的请求,这会将foo=bar
添加到下游请求的查询字符串中。
115.3 AddResponseHeader GatewayFilter 工厂
AddResponseHeader GatewayFilter 工厂采用名称和值参数。
application.yml.
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar
这会将X-Response-Foo:Bar
Headers 添加到所有匹配请求的下游响应的 Headers 中。
115.4 Hystrix GatewayFilter 工厂
Hystrix是 Netflix 的实现断路器模式的库。 Hystrix GatewayFilter 允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应。
要在您的项目中启用 Hystrix GatewayFilters,请从Spring Cloud Netflix添加对spring-cloud-starter-netflix-hystrix
的依赖。
Hystrix GatewayFilter 工厂需要一个name
参数,即HystrixCommand
的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://example.org
filters:
- Hystrix=myCommandName
这会将其余filter包装在命令名称为myCommandName
的HystrixCommand
中。
Hystrix filter还可以接受可选的fallbackUri
参数。当前,仅支持forward:
个计划的 URI。如果调用后备,则请求将被转发到与 URI 相匹配的控制器。
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 后备时,它将转发到/incaseoffailureusethis
URI。请注意,此示例还通过目标 URI 上的lb
前缀演示了(可选)Spring Cloud Netflix Ribbon 负载平衡。
主要方案是将fallbackUri
用于网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
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
终结点或处理程序,但是另一个应用程序中没有fallback
终结点或处理程序,并在http://localhost:9994
下注册。
如果将请求转发给后备,则 Hystrix 网关filter还会提供引起该请求的Throwable
。它已作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR
属性添加到ServerWebExchange
,可在网关应用程序中处理后备时使用。
对于外部控制器/处理程序方案,可以添加带有异常详细信息的 Headers。您可以在FallbackHeaders GatewayFilter 工厂部分中找到更多信息。
Hystrix 设置(例如超时)可以使用全局默认值配置,也可以使用Hystrix wiki上说明的应用程序属性在逐条路由的基础上进行配置。
要为上述示例路由设置 5 秒超时,将使用以下配置:
application.yml.
hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
115.5 FallbackHeaders GatewayFilter 工厂
FallbackHeaders
工厂允许您在转发到外部应用程序中fallbackUri
的请求的 Headers 中添加 Hystrix 执行异常详细信息,如以下情况:
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
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
在此示例中,在运行HystrixCommand
时发生执行异常后,该请求将转发到localhost:9994
上运行的应用程序中的fallback
端点或处理程序。带有异常类型,消息和-if available-根本原因异常类型和消息的 Headers 将由FallbackHeaders
filter添加到该请求。
通过设置下面列出的参数的值及其默认值,可以在配置中覆盖 Headers 的名称:
-
executionExceptionTypeHeaderName
("Execution-Exception-Type"
) -
executionExceptionMessageHeaderName
("Execution-Exception-Message"
) -
rootCauseExceptionTypeHeaderName
("Root-Cause-Exception-Type"
) -
rootCauseExceptionMessageHeaderName
("Root-Cause-Exception-Message"
)
您可以在Hystrix GatewayFilter 工厂部分中找到有关 Hystrix 如何与 Gateway 一起使用的更多信息。
115.6 PrefixPath GatewayFilter 工厂
PrefixPath GatewayFilter 工厂采用单个prefix
参数。
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- PrefixPath=/mypath
这会将/mypath
作为所有匹配请求的路径的前缀。因此,对/hello
的请求将发送到/mypath/hello
。
115.7 PreserveHostHeader GatewayFilter 工厂
PreserveHostHeader GatewayFilter 工厂没有参数。此filter设置请求属性,路由filter将检查该请求属性以确定是否应发送原始主机头,而不是由 HTTPClient 端确定的主机头。
application.yml.
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: http://example.org
filters:
- PreserveHostHeader
115.8 RequestRateLimiter GatewayFilter 工厂
RequestRateLimiter GatewayFilter 工厂使用RateLimiter
实现来确定是否允许 continue 当前请求。如果不是,则返回状态HTTP 429 - Too Many Requests
(默认)。
该filter采用可选的keyResolver
参数和特定于速率限制器的参数(请参见下文)。
keyResolver
是实现KeyResolver
接口的 bean。在配置中,使用 SpEL 按名称引用 bean。 #{@myKeyResolver}
是一个 SpEL 表达式,它引用名称为myKeyResolver
的 bean。
KeyResolver.java.
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver
接口允许可插拔策略派生用于限制请求的密钥。在 Future 的里程碑中,将有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-status-code
属性来调整此行为。
Note
无法通过“快捷方式”符号配置 RequestRateLimiter。以下示例是无效
application.properties.
# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
115.8.1 Redis RateLimiter
redis 实现基于Stripe完成的工作。它需要使用spring-boot-starter-data-redis-reactive
Spring Boot 启动程序。
使用的算法是令牌桶算法。
redis-rate-limiter.replenishRate
是您希望用户每秒允许多少个请求,而没有任何丢弃的请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity
是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。
通过在replenishRate
和burstCapacity
中设置相同的值可以达到稳定的速率。可以通过将burstCapacity
设置为高于replenishRate
来允许临时突发。在这种情况下,由于两次连续的突发将导致请求丢弃(HTTP 429 - Too Many Requests
),因此需要在两次突发之间有一定时间允许速率限制器(根据replenishRate
)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
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。
application.yml.
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: http://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolver}"
115.9 重定向到 GatewayFilter 工厂
RedirectTo GatewayFilter 工厂采用status
和url
参数。状态应该是 300 系列重定向 http 代码,例如 301.URL 应该是有效的 URL。这将是Location
Headers 的值。
application.yml.
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: http://example.org
filters:
- RedirectTo=302, http://acme.org
这将发送带有Location:http://acme.org
Headers 的状态 302 以执行重定向。
115.10 RemoveNonProxyHeaders GatewayFilter 工厂
RemoveNonProxyHeaders GatewayFilter 工厂从转发的请求中删除 Headers。默认的 Headers 列表来自IETF。
默认删除的标题为:
-
Connection
-
Keep-Alive
-
Proxy-Authenticate
-
Proxy-Authorization
-
TE
-
Trailer
-
Transfer-Encoding
-
Upgrade
要更改此设置,请将spring.cloud.gateway.filter.remove-non-proxy-headers.headers
属性设置为要删除的标题名称列表。
115.11 RemoveRequestHeader GatewayFilter 工厂
RemoveRequestHeader GatewayFilter 工厂采用name
参数。它是要删除的标题的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: http://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
这将删除X-Request-Foo
Headers,然后将其发送到下游。
115.12 RemoveResponseHeader GatewayFilter 工厂
RemoveResponseHeader GatewayFilter 工厂采用name
参数。它是要删除的标题的名称。
application.yml.
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
这将从响应中删除X-Response-Foo
Headers,然后将其返回给网关 Client 端。
115.13 RewritePath GatewayFilter 工厂
RewritePath GatewayFilter 工厂采用路径regexp
参数和replacement
参数。这使用 Java 正则表达式提供了一种灵活的方式来重写请求路径。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
对于/foo/bar
的请求路径,这将在发出下游请求之前将路径设置为/bar
。请注意,由于 YAML 规范,$\
被$
取代。
115.14 RewriteResponseHeader GatewayFilter 工厂
RewriteResponseHeader GatewayFilter 工厂采用name
,regexp
和replacement
参数。它使用 Java 正则表达式以灵活的方式重写响应 Headers 值。
application.yml.
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: http://example.org
filters:
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
对于 Headers 值/42?user=ford&password=omg!what&flag=true
,在发出下游请求后它将被设置为/42?user=ford&password=***&flag=true
。由于 YAML 规范,请使用$\
来表示$
。
115.15 SaveSession GatewayFilter 工厂
在向下游转发调用之前,SaveSession GatewayFilter 工厂强制执行WebSession::save
操作。这在将Spring Session之类的数据用于惰性数据存储时特别有用,并且需要确保在进行转接调用之前已保存会话状态。
application.yml.
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
如果您将Spring Security与 Spring Session 集成在一起,并且想要确保安全性详细信息已转发到远程进程,那么这一点至关重要。
115.16 SecureHeaders GatewayFilter 工厂
SecureHeaders GatewayFilter 工厂在来自此博客文章的建议处向响应中添加了许多 Headers。
添加以下 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
-
frame-options
-
content-type-options
-
referrer-policy
-
content-security-policy
-
download-options
-
permitted-cross-domain-policies
115.17 SetPath GatewayFilter 工厂
SetPath GatewayFilter 工厂采用路径template
参数。通过允许路径的模板段,它提供了一种操作请求路径的简单方法。这使用了 Spring Framework 中的 uri 模板。允许多个匹配段。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: http://example.org
predicates:
- Path=/foo/{segment}
filters:
- SetPath=/{segment}
对于/foo/bar
的请求路径,这将在发出下游请求之前将路径设置为/bar
。
115.18 SetResponseHeader GatewayFilter 工厂
SetResponseHeader GatewayFilter 工厂采用name
和value
参数。
application.yml.
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar
该 GatewayFilter 用给定名称替换所有 Headers,而不是添加。因此,如果下游服务器以X-Response-Foo:1234
响应,则将其替换为X-Response-Foo:Bar
,这是网关 Client 端将收到的内容。
115.19 SetStatus GatewayFilter 工厂
SetStatus GatewayFilter 工厂采用单个status
参数。它必须是有效的 Spring HttpStatus
。它可以是整数值404
或枚举NOT_FOUND
的字符串表示形式。
application.yml.
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
无论哪种情况,响应的 HTTP 状态都将设置为 401.
115.20 StripPrefix GatewayFilter 工厂
StripPrefix GatewayFilter 工厂采用一个参数parts
。 parts
参数指示在向下游发送请求之前,要从请求中剥离的路径中的部分数量。
application.yml.
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: http://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
通过网关向/name/bar/foo
发出请求时,向nameservice
发出的请求看起来像http://nameservice/foo
。
115.21 重试 GatewayFilter 工厂
重试 GatewayFilter 工厂将retries
,statuses
,methods
和series
作为参数。
-
retries
:应重试的次数 -
statuses
:应重试的 HTTP 状态代码,使用org.springframework.http.HttpStatus
表示 -
methods
:应重试的 HTTP 方法,使用org.springframework.http.HttpMethod
表示 -
series
:要重试的一系列状态代码,使用org.springframework.http.HttpStatus.Series
表示
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
Note
重试filter当前不支持使用主体重试(例如,使用主体进行 POST 或 PUT 请求)。
Note
当使用带有forward:
前缀 URL 的重试filter时,应仔细编写目标端点,以便在发生错误的情况下不会执行任何可能导致响应发送到 Client 端并提交的操作。例如,如果目标端点是带 Comments 的控制器,则目标控制器方法不应返回带有错误状态代码的ResponseEntity
。相反,它应该抛出Exception
或发出错误 signal,例如通过Mono.error(ex)
返回值,可以将重试filter配置为通过重试处理。
115.22 RequestSize GatewayFilter 工厂
当请求大小大于允许的限制时,RequestSize GatewayFilter Factory 可以限制请求到达下游服务。filter以RequestSize
作为参数,这是请求的允许大小限制(以字节为单位)。
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 Factory 将响应状态设置为413 Payload Too Large
,并附加一个 HeaderserrorMessage
。以下是此类errorMessage
的示例。
errorMessage
: Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
Note
如果未在路由定义中作为filter参数提供,则默认请求大小将设置为 5 MB。
115.23 修改请求正文 GatewayFilter 工厂
此filter被视为测试版,API 将来可能会更改
此filter可用于在网关将其发送到下游之前修改请求主体。
Note
只能使用 Java DSL 配置此filter
@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;
}
}
115.24 修改响应正文 GatewayFilter 工厂
此filter被视为测试版,API 将来可能会更改
此filter可用于在将响应正文发送回 Client 端之前对其进行修改。
Note
只能使用 Java DSL 配置此filter
@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();
}