Spring Cloud Gateway

2.2.0.BUILD-快照

该项目提供了一个建立在Spring Ecosystem之上的API网关,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为他们提供横切关注点,例如:安全性,监控/指标和弹性。

如何包含Spring Cloud Gateway

要在项目中包含Spring Cloud Gateway,请使用具有组org.springframework.cloud 和工件ID 的启动器spring-cloud-starter-gateway。有关 使用当前Spring Cloud Release Train设置构建系统的详细信息,请参阅Spring Cloud Project页面

如果包含启动器,但由于某种原因,您不希望启用网关,请进行设置spring.cloud.gateway.enabled=false

Spring Cloud Gateway基于Spring Boot 2.0Spring WebFluxProject Reactor 构建。因此,许多熟悉的同步库(例如Spring Data和Spring Security)和模式在使用Spring Cloud Gateway时可能不适用。如果您不熟悉这些项目,我们建议您在使用Spring Cloud Gateway之前先阅读他们的文档以熟悉一些新概念。

Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中工作或构建为WAR。

词汇表

  • Route: 路由网关的基本构建块。它由ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为真,则匹配路由。
  • Predicate: 这是一个Java 8函数谓词。输入类型是Spring FrameworkServerWebExchange。这允许开发人员匹配来自HTTP请求的任何内容,例如标头或参数。
  • Filter: 这是使用特定工厂构建的Spring FrameworkGatewayFilter实例。这里,可以在发送下游请求之前或之后修改请求和响应。

运行原理

运行原理

客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。此处理程序运行通过特定于请求的过滤器链发送请求。滤波器被虚线划分的原因是滤波器可以在发送代理请求之前或之后执行逻辑。执行所有“预”过滤器逻辑,然后进行代理请求。在发出代理请求之后,执行“post”过滤器逻辑。

在没有端口的路由中定义的URI将分别为HTTP和HTTPS URI获取默认端口设置为80和443。

Route Predicate Factories

Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础结构的一部分进行匹配。Spring Cloud Gateway包含许多内置的Route Predicate工厂。所有这些谓词都匹配HTTP请求的不同属性。多路线谓词工厂可以组合并通过逻辑组合and

After

After Route谓词工厂采用一个参数,一个日期时间。此谓词匹配在当前日期时间之后发生的请求。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]

此路由在2017年1月20日17:42 Mountain Time(Denver)之后的所有请求相匹配。

Before

Before Route Predicate Factory采用一个参数,一个日期时间。此谓词匹配在当前日期时间之前发生的请求。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: before_route
uri: http://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

此路由在2017年1月20日17:42 Mountain Time(Denver)之前的任何请求相匹配。

Between

Between Route Predicate Factory有两个参数,datetime1和datetime2。此谓词匹配datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: between_route
uri: http://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

此路路由在2017年1月20日17:42山地时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之前的任何请求相匹配。这对维护窗口很有用。

Cookie Route Predicate Factory有两个参数,cookie名称和正则表达式。此谓词匹配具有给定名称且值与正则表达式匹配的cookie。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://example.org
predicates:
- Cookie=chocolate, ch.p

此路由匹配请求具有名为chocolatewho的值与ch.p正则表达式匹配的cookie 。

Header Route谓词工厂采用两个参数,标题名称和正则表达式。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+

如果请求具有名称,X-Request-Id其值与\d+正则表达式匹配(具有一个或多个数字的值),则此路由匹配。

Host

Host Route Predicate Factory采用一个参数:主机名模式列表。该模式是一个Ant样式模式,.作为分隔符。此谓词匹配Host与模式匹配的标头。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org

如果请求的Host标头具有值www.somehost.orgbeta.somehost.orgwww.anotherhost.org,则此路由将匹配。

此谓词将URI模板变量(sub如上例中定义的)提取为名称和值的映射,并将其放在ServerWebExchange.getAttributes()带有定义的键的位置ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后,这些值可供GatewayFilter Factories使用

Method

Method Route Predicate Factory采用一个参数:要匹配的HTTP方法。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://example.org
predicates:
- Method=GET

如果请求方法是GET,则此路由将匹配。

Path

Path Route Predicate Factory有两个参数:Spring PathMatcher模式列表和一个可选标志matchOptionalTrailingSeparator

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Path=/foo/{segment},/bar/{segment}

如果请求路径是例如:/foo/1/foo/bar/bar/baz,则此路由将匹配。

此Predicate将URI模板变量(segment如上例中定义的)提取为名称和值的映射,并将其放在ServerWebExchange.getAttributes()带有定义的键的位置ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后,这些值可供GatewayFilter Factories使用

可以使用实用程序方法来更轻松地访问这些变量。

1
2
3
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);

String segment = uriVariables.get("segment");

Query

Query Route Predicate Factory有两个参数:必需param和可选regexp

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=baz

如果请求包含baz查询参数,则此路由将匹配。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=foo, ba.

如果请求包含foo其值为ba.regexp 匹配的查询参数,则此路由将匹配,因此bar并且baz将匹配。

RemoteAddr

RemoteAddr Route Predicate Factory采用CIDR符号(IPv4或IPv6)字符串的列表(最小值为1),例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子网掩码)。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://example.org
predicates:
- RemoteAddr=192.168.1.1/24

例如,如果请求的远程地址是192.168.1.10,则此路由将匹配。

修改远程地址的解析方式

默认情况下,RemoteAddr Route Predicate Factory使用传入请求中的远程地址。如果Spring Cloud Gateway位于代理层后面,则可能与实际客户端IP地址不匹配。

您可以通过设置自定义来自定义解析远程地址的方式RemoteAddressResolver。春季云网关来与基于关闭的一个非默认的远程地址解析器X -转发,对于头XForwardedRemoteAddressResolver

XForwardedRemoteAddressResolver 有两个静态构造函数方法,采用不同的安全方法:

XForwardedRemoteAddressResolver::trustAll返回一个RemoteAddressResolver始终采用X-Forwarded-For标头中找到的第一个IP地址的a 。这种方法容易受到欺骗,因为恶意客户端可以设置X-Forwarded-For解析器可以接受的初始值。

XForwardedRemoteAddressResolver::maxTrustedIndex获取与Spring Cloud Gateway前运行的可信基础架构数量相关的索引。例如,如果只能通过HAProxy访问Spring Cloud Gateway,则应使用值1。如果在可访问Spring Cloud Gateway之前需要两跳可信基础架构,则应使用值2。

给出以下标头值:

1
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

以下maxTrustedIndex值将产生以下远程地址。

maxTrustedIndex 结果
[ Integer.MIN_VALUE,0] IllegalArgumentException初始化期间无效)
1 0.0.0.3
2 0.0.0.2
3 0.0.0.1
[4,Integer.MAX_VALUE] 0.0.0.1

使用Java配置:

GatewayConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);

...

.route("direct-route",
r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
.uri("https://downstream1")
.route("proxied-route",
r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
.uri("https://downstream2")
)

Gateway Filter Factory

路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路径过滤器的范围限定为特定路径。Spring Cloud Gateway包含许多内置的GatewayFilter工厂。

注意有关如何使用以下任何过滤器的更详细示例,请查看单元测试

AddRequestHeader

AddRequestHeader GatewayFilter Factory采用名称和值参数。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar

这将为所有匹配请求的下游请求标头添加X-Request-Foo:Bar标头。

AddRequestParameter

AddRequestParameter GatewayFilter Factory采用名称和值参数。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: http://example.org
filters:
- AddRequestParameter=foo, bar

这将为所有匹配请求添加下游请求的查询字符串foo=bar

AddResponseHeader

AddResponseHeader GatewayFilter Factory采用名称和值参数。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: http://example.org
filters:
- AddResponseHeader=X-Response-Foo, Bar

DedupeResponseHeader

DedupeResponseHeader GatewayFilter Factory接受name参数和可选strategy参数。name可以包含标题名称列表,空格分隔。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: http://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

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

DedupeResponseHeader过滤器还接受可选strategy参数。接受的值是RETAIN_FIRST(默认)、RETAIN_LASTRETAIN_UNIQUE

Hystrix

Hystrix是Netflix的一个库,它实现了断路器模式。Hystrix GatewayFilter允许您将断路器引入网关路由,保护您的服务免受级联故障的影响,并允许您在下游故障时提供回退响应。

要在项目中启用Hystrix GatewayFilters,请spring-cloud-starter-netflix-hystrixSpring Cloud Netflix添加依赖项。

Hystrix GatewayFilter Factory需要一个name参数,即该参数的名称HystrixCommand

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

这将HystrixCommand使用命令名称包装剩余的过滤器myCommandName

Hystrix过滤器也可以接受可选fallbackUri参数。目前,仅forward:支持计划的URI。如果调用了回退,则请求将被转发到与URI匹配的控制器。

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

这将/incaseoffailureusethis在调用Hystrix回退时转发到URI。请注意,此示例还通过lb目标URI 上的前缀演示(可选)Spring Cloud Netflix Ribbon负载平衡。

主要方案是使用fallbackUri网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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网关应用程序中没有端点或处理程序,但是,在另一个应用程序中有一个,在其下注册http://localhost:9994

如果请求被转发到回退,Hystrix网关过滤器也会提供Throwable导致它的原因。它被添加到ServerWebExchange作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR在网关应用程序中处理回退时可以使用的 属性。

对于外部控制器/处理程序方案,可以添加包含异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。

Hystrix设置(例如超时)可以使用全局默认值配置,也可以使用应用程序属性逐个路径配置,如Hystrix wiki中所述

要为上面的示例路由设置5秒超时,将使用以下配置:

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

FallbackHeaders

FallbackHeaders工厂可以让你在转发到请求的头部添加猬执行异常的详细信息fallbackUri在以下情况下在外部应用程序,如:

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: 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,请求将被转发到fallback运行的应用程序中的端点或处理程序localhost:9994。具有异常类型,消息和-if available-root的标头将导致异常类型和消息被FallbackHeaders过滤器添加到该请求中。

通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:

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

您可以在Hystrix GatewayFilter Factory部分中找到有关Hystrix如何与Gateway配合使用的更多信息。

PrefixPath

PrefixPath GatewayFilter Factory采用单个prefix参数。

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

这将为/mypath所有匹配请求的路径添加前缀。所以请求/hello,将发送给/mypath/hello

PreserveHostHeader

PreserveHostHeader GatewayFilter Factory没有参数。此过滤器设置路由过滤器将检查的请求属性,以确定是否应发送原始主机头,而不是http客户端确定的主机头。

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

RequestRateLimiter

RequestRateLimiter GatewayFilter Factory使用RateLimiter实现来确定是否允许当前请求继续。如果不是,HTTP 429 - Too Many Requests则返回(默认情况下)状态。

此过滤器采用keyResolver特定于速率限制器的可选参数和参数(参见下文)。

keyResolver是一个实现KeyResolver接口的bean 。在配置中,使用SpEL按名称引用bean。#{@myKeyResolver}是一个引用具有名称的bean的SpEL表达式myKeyResolver

KeyResolver.java

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

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

默认实现KeyResolver是从和调用中PrincipalNameKeyResolver检索。Principal`ServerWebExchangePrincipal.getName()`

默认情况下,如果KeyResolver找不到密钥,将拒绝请求。可以使用spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true或false)和spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性调整此行为。

RequestRateLimiter不能通过“快捷方式”表示法进行配置。以下示例无效

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

Redis RateLimiter

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

使用的算法是令牌桶算法

redis-rate-limiter.replenishRate是您希望允许用户每秒执行多少请求,而不会丢弃任何请求。这是令牌桶填充的速率。

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

通过在replenishRate和中设置相同的值来实现稳定的速率burstCapacity。设置burstCapacity高于时,可以允许临时突发replenishRate。在这种情况下,需要在突发之间允许速率限制器一段时间(根据replenishRate),因为2次连续突发将导致请求被丢弃(HTTP 429 - Too Many Requests)。

1
2
3
4
5
6
7
8
9
10
11
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

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

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

速率限制器也可以定义为实现RateLimiter接口的bean 。在配置中,使用SpEL按名称引用bean。#{@myRateLimiter}是一个引用具有名称的bean的SpEL表达式myRateLimiter

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

RedirectTo

RedirectTo GatewayFilter Factory采用a statusurl参数。状态应该是300系列重定向http代码,例如301. url应该是有效的URL。这将是Location标题的值。

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

这将发送带有Location:http://acme.org标题的状态302 以执行重定向。

RemoveHopByHopHeadersFilter

RemoveHopByHopHeadersFilter GatewayFilter Factory从转发的请求中删除标头。删除的标头列表来自IETF

默认删除的标头是:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade

要更改此设置,请将该spring.cloud.gateway.filter.remove-non-proxy-headers.headers属性设置为要删除的标题名称列表。

RemoveRequestHeader

RemoveRequestHeader GatewayFilter Factory接受一个name参数。它是要删除的标头的名称。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: http://example.org
filters:
- RemoveRequestHeader=X-Request-Foo

这将在向下游发送之前删除标头X-Request-Foo

RemoveResponseHeader

RemoveResponseHeader GatewayFilter Factory接受一个name参数。它是要删除的标头的名称。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: http://example.org
filters:
- RemoveResponseHeader=X-Response-Foo

这将X-Response-Foo在响应返回到网关客户端之前从响应中删除标头。

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

RewritePath

RewritePath GatewayFilter Factory采用路径regexp参数和replacement参数。这使用Java正则表达式来灵活地重写请求路径。

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

对于请求路径/foo/bar,这将设置/bar进行下游请求之前的路径。注意由于YAML规范而将$\替换$

RewriteResponseHeader

RewriteResponseHeader GatewayFilter工厂需要nameregexpreplacement参数。它使用Java正则表达式以灵活的方式重写响应头值。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: http://example.org
filters:
- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***

对于标头值/42?user=ford&password=omg!what&flag=true,它将在发出下游请求后设置为/42?user=ford&password=***&flag=true。由于YAML规范,请用$\替换$

SaveSession

SaveSession GatewayFilter Factory 转发下游呼叫之前强制执行WebSession::save操作。当使用Spring Session与惰性数据存储之类的东西时,这是特别有用的,并且需要确保在转发调用之前已保存会话状态。

1
2
3
4
5
6
7
8
9
10
spring:
cloud:
gateway:
routes:
- id: save_session
uri: http://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession

如果要将Spring Security与Spring Session 集成,并且希望确保将安全性详细信息转发到远程进程,则这很关键。

SecureHeaders

SecureHeaders GatewayFilter Factory在此博客文章的推荐中为响应添加了许多标题。

添加以下标头(以及默认值):

  • 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

SetPath

SetPath GatewayFilter Factory采用路径template参数。它提供了一种通过允许模板化路径段来操作请求路径的简单方法。这使用了Spring Framework中的uri模板。允许多个匹配的段。

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

对于请求路径/foo/bar,这将设置/bar进行下游请求之前的路径。

SetResponseHeader

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: http://example.org
filters:
- SetResponseHeader=X-Response-Foo, Bar

GatewayFilter用给定名称替换所有标头,而不是添加。因此,如果下游服务器以响应X-Response-Foo:1234,则将替换为X-Response-Foo:Bar,这是网关客户端将接收的内容。

SetStatus

SetStatus GatewayFilter Factory采用单个status参数。它必须是有效的Spring HttpStatus。它可以是整数值404或枚举的字符串表示形式NOT_FOUND

1
2
3
4
5
6
7
8
9
10
11
12
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。

StripPrefix

StripPrefix GatewayFilter Factory采用一个参数parts。该parts参数指示在向下游发送之前从请求中剥离的路径中的部分数。

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

当通过网关/name/bar/foo发出请求时,nameservice会发出请求http://nameservice/foo

Retry

Retry GatewayFilter 工厂采用retriesstatusesmethods,和series作为参数。

  • retries:应尝试的重试次数
  • statuses:应使用重试的HTTP状态代码 org.springframework.http.HttpStatus
  • methods:应该重试的HTTP方法,使用表示 org.springframework.http.HttpMethod
  • series:要重试的一系列状态代码,使用表示 org.springframework.http.HttpStatus.Series
1
2
3
4
5
6
7
8
9
10
11
12
13
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

重试过滤器当前不支持使用正文重试(例如,对于带有正文的POST或PUT请求)。

当使用带有forward:前缀URL 的重试过滤器时,应仔细编写目标端点,以便在出现错误时不会执行任何可能导致响应发送到客户端并提交的操作。例如,如果目标端点是带注释的控制器,则目标控制器方法不应返回ResponseEntity错误状态代码。相反,它应该抛出一个Exception或发出错误信号,例如通过Mono.error(ex)返回值,重试过滤器可以配置为通过重试来处理。

RequestSize

当请求大小大于允许的限制时,RequestSize GatewayFilter Factory可以限制请求到达下游服务。过滤器RequestSize作为参数,该参数是以字节为单位定义的请求的允许大小限制。

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

当Request因大小而被拒绝时,RequestSize GatewayFilter Factory将响应状态设置为413 Payload Too Large附加标头errorMessage。以下是这样的一个例子errorMessage

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

如果未在路由定义中将过滤参数提供,则默认请求大小将设置为5 MB。

Modify Request Body

此过滤器被视为BETA,API可能在将来发生变化

此过滤器可用于在网关向下游发送请求主体之前对其进行修改。

此过滤器只能使用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;
}
}

Modify Response Body

此过滤器被视为BETA,API可能在将来发生变化

此过滤器可用于在将响应主体发送回客户端之前对其进行修改。

此过滤器只能使用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();
}

Default Filters

如果您想添加过滤器并将其应用于您可以使用的所有路线spring.cloud.gateway.default-filters。此属性采用过滤器列表

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

Global Filters

GlobalFilter接口具有相同的签名GatewayFilter。这些是有条件地应用于所有路线的特殊过滤器。(此界面和用法可能会在未来的里程碑中发生变化)。

组合全局过滤器和GatewayFilter排序

当请求进入(并匹配路由)时,Filtering Web Handler会将所有实例GlobalFilter和所有路由特定实例添加GatewayFilter到过滤器链中。这个组合的过滤器链按org.springframework.core.Ordered接口排序,可以通过实现getOrder()方法或使用@Order注释来设置。

由于Spring Cloud Gateway区分了过滤器逻辑执行的“前”和“后”阶段(请参阅:工作原理),具有最高优先级的过滤器将是“pre”阶段中的第一个和“post”中的最后一个“-相。

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
28
29
30
31
32
@Bean
@Order(-1)
public GlobalFilter a() {
return (exchange, chain) -> {
log.info("first pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("third post filter");
}));
};
}

@Bean
@Order(0)
public GlobalFilter b() {
return (exchange, chain) -> {
log.info("second pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("second post filter");
}));
};
}

@Bean
@Order(1)
public GlobalFilter c() {
return (exchange, chain) -> {
log.info("third pre filter");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("first post filter");
}));
};
}

Forward Routing Filter

ForwardRoutingFilter在交换属性查找一个URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果url有一个forward方案(即forward:///localendpoint),它将使用Spring DispatcherHandler来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。

LoadBalancerClient过滤器

LoadBalancerClientFilter在交换属性查找一个URI ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR。如果url有一个lb方案(即lb://myservice),它将使用Spring Cloud LoadBalancerClient将名称(myservice在前面的示例中)解析为实际的主机和端口,并替换相同属性中的URI。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性以查看它是否等于lb,然后应用相同的规则。

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: lb://service
predicates:
- Path=/service/**

默认情况下,当某个服务实例不能在找到LoadBalancer一个503将被退回。您可以将网关配置为404按设置返回spring.cloud.gateway.loadbalancer.use404=true

从中返回 的isSecure值将覆盖在对网关发出的请求中指定的方案。例如,如果请求进入网关, 但表示它不安全,则下游请求将被终止 。相反的情况也适用。但是,如果为网关配置中的路由指定,则将剥离前缀,并且路由URL中的结果方案将覆盖配置。 ServiceInstance LoadBalancer HTTPS ServiceInstance HTTP GATEWAY_SCHEME_PREFIX_ATTR ServiceInstance

Netty Routing Filter

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange属性中的url 具有httphttpsscheme ,则运行Netty Routing Filter 。它使用Netty HttpClient发出下游代理请求。响应将放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTRexchange属性中,以便在以后的过滤器中使用。(有一个实验WebClientHttpRoutingFilter执行相同的功能,但不需要netty)

Netty Write Response Filter

NettyWriteResponseFilter运行,如果有一个的Netty HttpClientResponseServerWebExchangeUtils.CLIENT_RESPONSE_ATTR交换属性。它在所有其他过滤器完成后运行,并将代理响应写回网关客户端响应。(有一个实验WebClientWriteResponseFilter执行相同的功能,但不需要netty)

RouteToRequestUrl过滤器

RouteToRequestUrlFilter运行,如果有一个Route在对象ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR交换属性。它根据请求URI创建一个新URI,但使用该Route对象的URI属性进行更新。新URI放在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange属性`中。

如果URI具有方案前缀,例如lb:ws://serviceid,该lb方案将从URI中剥离并放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR稍后用于过滤器链中。

Websocket路由过滤器

如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange属性中的url 具有wswssscheme ,则运行Websocket路由过滤器。它使用Spring Web Socket基础结构将Websocket请求转发到下游。

可以通过为URI添加前缀来对Websockets进行负载平衡lb,例如lb:ws://serviceid

如果您使用SockJS作为普通http的后备,则应配置正常的HTTP路由以及Websocket路由。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
cloud:
gateway:
routes:
# SockJS route
- id: websocket_sockjs_route
uri: http://localhost:3001
predicates:
- Path=/websocket/info/**
# Normwal Websocket route
- id: websocket_route
uri: ws://localhost:3001
predicates:
- Path=/websocket/**

Gateway Metrics Filter

要启用Gateway Metrics,请将spring-boot-starter-actuator添加为项目依赖项。然后,默认情况下,只要spring.cloud.gateway.metrics.enabled未将属性设置为,网关指标筛选器就会运行false。此过滤器添加名为“gateway.requests”的计时器度量标准,其中包含以下标记:

  • routeId:路由ID
  • routeUri:API将路由到的URI
  • outcome:由HttpStatus.Series分类的结果
  • status:请求的Http状态返回给客户端

然后可以从这些指标中删除这些指标,/actuator/metrics/gateway.requests并且可以轻松地与Prometheus 集成 以创建Grafana 仪表板

要启用pometheus端点,请将micrometer-registry-prometheus添加为项目依赖项。

Marking An Exchange As Routed

在网关路由后ServerWebExchange,它将通过添加gatewayAlreadyRouted 到交换属性将该交换标记为“路由” 。一旦请求被标记为路由,其他路由过滤器将不会再次路由请求,实质上是跳过过滤器。您可以使用便捷方法将交换标记为路由,或检查交换是否已路由。

  • ServerWebExchangeUtils.isAlreadyRouted获取一个ServerWebExchange对象并检查它是否已被“路由”
  • ServerWebExchangeUtils.setAlreadyRouted获取一个ServerWebExchange对象并将其标记为“路由”

TLS / SSL

网关可以通过遵循通常的Spring服务器配置来监听https上的请求。例:

1
2
3
4
5
6
7
server:
ssl:
enabled: true
key-alias: scg
key-store-password: scg1234
key-store: classpath:scg-keystore.p12
key-store-type: PKCS12

网关路由可以路由到http和https后端。如果路由到https后端,则可以将网关配置为信任具有以下配置的所有下游证书:

1
2
3
4
5
6
spring:
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true

使用不安全的信任管理器不适合生产。对于生产部署,可以使用以下配置为Gateway配置一组可信任的已知证书:

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
httpclient:
ssl:
trustedX509Certificates:
- cert1.pem
- cert2.pem

如果Spring Cloud Gateway未配置受信任证书,则使用默认信任库(可以使用系统属性javax.net.ssl.trustStore覆盖)。

TLS Handshake

网关维护一个客户端池,用于路由到后端。通过https进行通信时,客户端会启动TLS握手。此握手与许多超时有关。可以配置这些超时(显示默认值):

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
httpclient:
ssl:
handshake-timeout-millis: 10000
close-notify-flush-timeout-millis: 3000
close-notify-read-timeout-millis: 0

Configuration

Spring Cloud Gateway的配置由RouteDefinitionLocators的集合驱动。

RouteDefinitionLocator.java

1
2
3
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}

默认情况下,PropertiesRouteDefinitionLocator使用Spring Boot的@ConfigurationProperties机制加载属性。

上面的配置示例都使用了一个使用位置参数而不是命名参数的快捷符号。以下两个例子是等效的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
cloud:
gateway:
routes:
- id: setstatus_route
uri: http://example.org
filters:
- name: SetStatus
args:
status: 401
- id: setstatusshortcut_route
uri: http://example.org
filters:
- SetStatus=401

对于网关的一些用法,属性是足够的,但是一些生产用例将受益于从外部源(例如数据库)加载配置。未来的里程碑版本将RouteDefinitionLocator基于Spring Data Repositories实现,例如:Redis,MongoDB和Cassandra。

流畅的Java Routes API

为了允许在Java中进行简单配置,在RouteLocatorBuilderbean中定义了一个流畅的API 。

GatewaySampleApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// static imports from GatewayFilters and RoutePredicates
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
return builder.routes()
.route(r -> r.host("**.abc.org").and().path("/image/png")
.filters(f ->
f.addResponseHeader("X-TestHeader", "foobar"))
.uri("http://httpbin.org:80")
)
.route(r -> r.path("/image/webp")
.filters(f ->
f.addResponseHeader("X-AnotherHeader", "baz"))
.uri("http://httpbin.org:80")
)
.route(r -> r.order(-1)
.host("**.throttle.org").and().path("/get")
.filters(f -> f.filter(throttle.apply(1,
1,
10,
TimeUnit.SECONDS)))
.uri("http://httpbin.org:80")
)
.build();
}

此样式还允许更多自定义谓词断言。RouteDefinitionLocatorbean 定义的谓词使用逻辑组合and。通过使用流利的Java API,你可以使用and()or()并且negate()对运营Predicate类。

DiscoveryClient路由定义定位器

可以将网关配置为基于使用DiscoveryClient兼容服务注册表注册的服务来创建路由。

要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true并确保DiscoveryClient实现位于类路径上并启用(例如Netflix Eureka,Consul或Zookeeper)。

配置DiscoveryClient路由的谓词和过滤器

默认情况下,网关为通过a创建的路由定义单个谓词和过滤器DiscoveryClient

默认谓词是使用模式定义的路径谓词/serviceId/**,其中serviceId是来自的服务的id DiscoveryClient

默认过滤器是带有正则表达式/serviceId/(?<remaining>.*)和替换的 重写路径过滤器/${remaining}。这只是在向下游发送请求之前从路径中剥离服务ID。

如果您想自定义DiscoveryClient路由使用的谓词和/或过滤器,可以通过设置spring.cloud.gateway.discovery.locator.predicates[x]和来自定义spring.cloud.gateway.discovery.locator.filters[y]。执行此操作时,如果要保留该功能,则需要确保包含上面的默认谓词和过滤器。下面是一个这样的例子。

1
2
3
4
5
6
7
8
9
spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

Reactor Netty访问日志

要启用Reactor Netty访问日志,请进行设置-Dreactor.netty.http.server.accessLogEnabled=true。(它必须是Java System属性,而不是Spring Boot属性)。

可以将日志记录系统配置为具有单独的访问日志文件。以下是一个示例logback配置:

logback.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<appender name="accessLog" class="ch.qos.logback.core.FileAppender">
<file>access_log.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="accessLog" />
</appender>

<logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
<appender-ref ref="async"/>
</logger>

CORS配置

网关可以配置为控制CORS行为。“全局”CORS配置是Spring FrameworkCorsConfiguration的URL模式映射。

1
2
3
4
5
6
7
8
9
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://docs.spring.io"
allowedMethods:
- GET

在上面的示例中,对于所有GET请求的路径,将允许来自docs.spring.io的请求的CORS请求。

Actuator API

/gateway驱动器的端点允许监视和使用Spring的云网关应用程序进行交互。要进行远程访问,必须在应用程序属性中通过HTTP或JMX 启用公开端点。

1
2
management.endpoint.gateway.enabled=true # default value
management.endpoints.web.exposure.include=gateway

检索路由过滤器

全球过滤器

要检索应用于所有路由的全局过滤器,请发出GET请求/actuator/gateway/globalfilters。结果响应类似于以下内容:

1
2
3
4
5
6
7
8
9
10
{
"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5": 10100,
"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,
"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,
"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,
"org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647,
"org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0,
"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,
"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646
}

响应包含有关全局过滤器的详细信息。对于每个全局过滤器,提供过滤器对象的字符串表示(例如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5)和过滤器链中的对应顺序

Route过滤器

要检索应用于路由的GatewayFilter工厂,请发出GET请求/actuator/gateway/routefilters。结果响应类似于以下内容:

1
2
3
4
5
{
"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}

响应包含应用于任何特定路由的GatewayFilter工厂的详细信息。为每个工厂提供相应对象的字符串表示(例如[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,该null值是由于端点控制器的实现不完整,因为它尝试设置过滤器链中对象的顺序,这不适用于GatewayFilter工厂对象。

刷新路由缓存

要清除路由缓存,请发出POST请求/actuator/gateway/refresh。请求返回200没有响应正文

检索网关中定义的路由

要检索网关中定义的路由,请发出GET请求/actuator/gateway/routes。结果响应类似于以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[{
"route_id": "first_route",
"route_object": {
"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d",
"filters": [
"OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"
]
},
"order": 0
},
{
"route_id": "second_route",
"route_object": {
"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298",
"filters": []
},
"order": 0
}]

响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(即路由)的结构。

路径 类型 描述
route_id String 路由ID
route_object.predicate Object 路由断言
route_object.filters Array GatewayFilter工厂工厂使用的路由
order Number 路由顺序

检索有关特定路线的信息

要检索有关单个路径的信息,GET请向/actuator/gateway/routes/{id}(例如/actuator/gateway/routes/first_route)发出请求。结果响应类似于以下内容:

1
2
3
4
5
6
7
8
9
10
{
"id": "first_route",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"/first"}
}],
"filters": [],
"uri": "http://www.uri-destination.org",
"order": 0
}]

下表描述了响应的结构:

路径 类型 描述
id String 路由ID
predicates Array 路由断言的集合。每个项目定义给定断言的名称和参数
filters Array 应用于路径的过滤器集合
uri String 路由的目标URI
order Number 路由顺序

创建和删除特定路线

要创建路由,POST/gateway/routes/{id_route_to_create}使用指定路径字段的JSON主体发出请求(请参阅上一小节)。

要删除路线,请发出DELETE请求/gateway/routes/{id_route_to_delete}

回顾:所有端点的列表

下表总结了Spring Cloud Gateway执行器端点。请注意,每个端点都具有/actuator/gateway基本路径。

ID HTTP方法 描述
globalfilters GET 显示应用于路径的全局过滤器列表
routefilters GET 显示应用于特定路由的GatewayFilter工厂列表
refresh POST 清除路由缓存
routes GET 显示网关中定义的路由列表
routes/{id} GET 显示有关特定路径的信息
routes/{id} POST 添加到网关的新路由
routes/{id} DELETE 从网关中删除现有路由

开发者指南

TODO:编写自定义集成的概述

编写自定义路由断言工厂

TODO:撰写Custom Route Predicate Factories的文档

编写自定义GatewayFilter工厂

要编写GatewayFilter,您需要实现GatewayFilterFactory。有一个AbstractGatewayFilterFactory可以扩展的抽象类:

PreGatewayFilterFactory.java

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(request).build());
};
}

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

}

PostGatewayFilterFactory.java

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

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

@Override
public GatewayFilter apply(Config config) {
// grab configuration from Config object
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
//Manipulate the response in some way
}));
};
}

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

}

编写定制全局过滤器

要编写自定义全局过滤器,您需要实现GlobalFilter接口。这将过滤器应用于所有请求。

分别如何设置全局前置和后置过滤器的示例

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
@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> exchange.getPrincipal()
.map(Principal::getName)
.defaultIfEmpty("Default User")
.map(userName -> {
//adds header to proxied request
exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
return exchange;
})
.flatMap(chain::filter);
}

@Bean
public GlobalFilter customGlobalPostFilter() {
return (exchange, chain) -> chain.filter(exchange)
.then(Mono.just(exchange))
.map(serverWebExchange -> {
//adds header to response
serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
return serverWebExchange;
})
.then();
}

编写自定义路由定位器和写入器

TODO:编写自定义路由定位器和写入器的文档

使用Spring MVC或Webflux构建简单网关

Spring Cloud Gateway提供了一个实用程序对象ProxyExchange,可以在常规Spring Web处理程序中将其用作方法参数。它通过镜像HTTP谓词的方法支持基本的下游HTTP交换。使用MVC,它还支持通过该forward()方法转发到本地处理程序。要ProxyExchange在类路径中使用恰好包含正确的模块(spring-cloud-gateway-mvc或者spring-cloud-gateway-webflux)。

MVC示例(代理向远程服务器下游“/test”的请求):

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@SpringBootApplication
public class GatewaySampleApplication {

@Value("${remote.home}")
private URI home;

@GetMapping("/test")
public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
return proxy.uri(home.toString() + "/image/png").get();
}

}

Webflux也是如此:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@SpringBootApplication
public class GatewaySampleApplication {

@Value("${remote.home}")
private URI home;

@GetMapping("/test")
public Mono<ResponseEntity<?>> proxy(ProxyExchange<byte[]> proxy) throws Exception {
return proxy.uri(home.toString() + "/image/png").get();
}

}

有一些方便的方法ProxyExchange可以使处理程序方法发现和增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将其传递到下游:

1
2
3
4
5
@GetMapping("/proxy/path/**")
public ResponseEntity<?> proxyPath(ProxyExchange<byte[]> proxy) throws Exception {
String path = proxy.path("/proxy/path/");
return proxy.uri(home.toString() + "/foos/" + path).get();
}

Spring MVC或Webflux的所有功能都可用于Gateway处理程序方法。例如,您可以注入请求标头和查询参数,并且您可以使用映射注释中的声明来约束传入的请求。有关@RequestMapping这些功能的更多详细信息,请参阅Spring MVC中的文档。

可以使用header()方法将标头添加到下游响应中ProxyExchange

您还可以通过向get()etc方法添加映射器来操作响应标头(以及响应中您喜欢的任何其他内容)。映射器是一个Function接收传入ResponseEntity并将其转换为传出映射器的映射器。

为“敏感”标题(默认情况下为“cookie”和“授权”)提供了第一类支持,这些标题未传递到下游,而“代理”标题(x-forwarded-*)也是如此。