Spring Cloud网关
Greenwich SR5
该项目提供了一个基于Spring生态系统的API网关,其中包括:Spring 5,Spring Boot 2和项目Reactor。Spring Cloud网关的目的是提供一种简单而有效的方法来路由到API,并向它们提供跨领域的关注,例如:安全性,监视/度量和弹性。
如何包括Spring Cloud网关
要将Spring Cloud网关包含在项目中,请将该启动器与组org.springframework.cloud
和工件ID spring-cloud-starter-gateway
一起使用。有关 使用当前Spring Cloud版本Train设置构建系统的详细信息,请参见Spring Cloud项目页面。
如果包括启动器,但由于某种原因,您不希望启用网关,请设置spring.cloud.gateway.enabled=false
。
重要 | |
---|---|
Spring Cloud网关基于Spring Boot 2.x, Spring WebFlux和项目Reactor 构建。因此,使用Spring Cloud网关时,许多熟悉的同步库(例如,Spring Data和Spring Security)和模式可能不适用。如果您不熟悉这些项目,建议您在使用Spring Cloud Gateway之前,先阅读它们的文档以熟悉一些新概念。 |
重要 | |
---|---|
Spring Cloud网关需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中或作为WAR构建。 |
111.词汇表
- 路由:路由网关的基本构建块。它由ID,目标URI,谓词集合和过滤器集合定义。如果聚合谓词为true,则匹配路由。
- 谓词:这是 Java 8 Function谓词。输入类型为 Spring Framework ServerWebExchange。这使开发人员可以匹配HTTP请求中的任何内容,例如标头或参数。
- 过滤器:这些是使用特定工厂构造的实例 Spring Framework GatewayFilter。在此,可以在发送下游请求之前或之后修改请求和响应。
112.工作原理
客户端向Spring Cloud网关发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序运行通过特定于请求的筛选器链发送请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前或之后执行逻辑。执行所有“前置”过滤器逻辑,然后发出代理请求。发出代理请求后,将执行“后”过滤器逻辑。
在没有端口的路由中定义的URI将分别将HTTP和HTTPS URI的默认端口分别设置为80和443。 |
113.配置路由谓词工厂和网关过滤工厂
有两种配置谓词和过滤器的方法:快捷方式和完全扩展的参数。下面的大多数示例都使用快捷方式。
名称和自变量名称将在第一部分或每部分的两个部分中以code
的形式列出。参数通常按快捷方式配置所需的顺序列出。
113.1快捷方式配置
快捷方式配置由过滤器名称识别,后跟等号(=
),后跟由逗号分隔的参数值(,
)。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Cookie</span>=mycookie,mycookievalue</span></span></span>
先前的示例使用两个参数定义了Cookie
Route Predicate Factory,即cookie名称mycookie
和与mycookievalue
相匹配的值。
113.2完全展开的参数
完全扩展的参数看起来更像带有名称/值对的标准Yaml配置。通常,将有一个name
键和一个args
键。args
键是用于配置谓词或过滤器的键值对的映射。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - name</span>: Cookie
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: mycookie
<span style="color:#7f007f"> regexp</span>: mycookievalue</span></span></span>
这是上面显示的Cookie
谓词的快捷方式配置的完整配置。
114.路由谓词工厂
Spring Cloud网关将路由匹配为Spring WebFlux HandlerMapping
基础结构的一部分。Spring Cloud网关包括许多内置的Route Predicate工厂。所有这些谓词都与HTTP请求的不同属性匹配。多个路由谓词工厂可以合并,也可以通过逻辑and
合并。
114.1路由谓词工厂之后
After
路由谓词工厂采用一个参数,即datetime
(这是Java ZonedDateTime
)。该谓词匹配在当前日期时间之后发生的请求。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: after_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - After</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
该路线与2017年1月20日17:42山区时间(丹佛)之后的所有请求匹配。
114.2路线谓词工厂之前
Before
路由谓词工厂采用一个参数datetime(它是Java ZonedDateTime
)。该谓词匹配当前日期时间之前发生的请求。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: before_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Before</span>=2017-01-20T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
该路线与2017年1月20日17:42山区时间(丹佛)之前的所有请求匹配。
114.3路由谓词工厂之间
Between
路由谓词工厂采用两个参数datetime1
和datetime2
,它们是Java ZonedDateTime
对象。该谓词匹配在datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: between_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Between</span>=2017-01-20T17:42:47.789-07:00[America/Denver]<span style="color:#7f0055"><strong>,</strong></span> 2017-01-21T17:42:47.789-07:00[America/Denver<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
该路线与2017年1月20日山区时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之后的所有请求匹配。这对于维护时段可能很有用。
114.4 Cookie路线谓词工厂
Cookie
Route Predicate Factory采用两个参数,即cookie name
和regexp
(这是Java正则表达式)。该谓词匹配具有给定名称的cookie,并且值匹配正则表达式。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: cookie_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Cookie</span>=chocolate<span style="color:#7f0055"><strong>,</strong></span> ch.p</span></span></span>
此路由与请求匹配,具有一个名为chocolate
的cookie,该cookie的值与ch.p
正则表达式匹配。
114.5标头路由谓词工厂
Header
Route Predicate Factory具有两个参数,标头name
和regexp
(这是Java正则表达式)。该谓词与具有给定名称的标头匹配,并且值与正则表达式匹配。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Header</span>=X-Request-Id<span style="color:#7f0055"><strong>,</strong></span> \d+</span></span></span>
如果请求具有名为X-Request-Id
的标头,且其值与\d+
正则表达式匹配(具有一个或多个数字的值),则此路由匹配。
114.6主机路由谓词工厂
Host
Route Predicate Factory采用一个参数:主机名patterns
的列表。模式是Ant样式的模式,以.
作为分隔符。该谓词与匹配模式的Host
头匹配。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>=**.somehost.org,**.anotherhost.org</span></span></span>
还支持URI模板变量,例如{sub}.myhost.org
。
如果请求的Host
标头的值为www.somehost.org
或beta.somehost.org
或www.anotherhost.org
,则此路由将匹配。
该谓词提取URI模板变量(如上例中定义的sub
)作为名称和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定义的键将其放置在ServerWebExchange.getAttributes()
中。这些值可供GatewayFilter工厂使用。
114.7方法路线谓词工厂
Method
路由谓词工厂采用一个methods
参数,该参数是一个或多个要匹配的HTTP方法。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: method_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Method</span>=GET,POST</span></span></span>
如果请求方法是GET
或POST
,则此路由将匹配。
114.8路径路线谓词工厂
Path
路由谓词工厂采用两个参数:Spring PathMatcher
patterns
的列表和matchOptionalTrailingSeparator
的可选标志。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment},/bar/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
如果请求路径为例如/foo/1
或/foo/bar
或/bar/baz
,则此路由将匹配。
该谓词提取URI模板变量(如以上示例中定义的segment
)作为名称和值的映射,并使用在ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
中定义的键将其放置在ServerWebExchange.getAttributes()
中。这些值可供GatewayFilter工厂使用。
可以使用实用程序方法来简化对这些变量的访问。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get(<span style="color:#2a00ff">"segment"</span>);</span></span></span>
114.9查询路由谓词工厂
Query
Route Predicate Factory采用两个参数:必需的param
和可选的regexp
(这是Java正则表达式)。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: query_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Query</span>=baz</span></span></span>
如果请求包含baz
查询参数,则此路由将匹配。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: query_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Query</span>=foo<span style="color:#7f0055"><strong>,</strong></span> ba.</span></span></span>
如果请求包含一个foo
查询参数,其值与ba.
正则表达式匹配,则此路由将匹配,因此bar
和baz
将匹配。
114.10 RemoteAddr路由谓词工厂
RemoteAddr
路由谓词工厂采用sources
的列表(最小大小1),它是CIDR表示法(IPv4或IPv6)字符串,例如192.168.0.1/16
(其中192.168.0.1
是IP地址, 16
是子网掩码)。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: remoteaddr_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - RemoteAddr</span>=192.168.1.1/24</span></span></span>
如果请求的远程地址为192.168.1.10
,则此路由将匹配。
114.11重量路线谓词工厂
Weight
Route Predicate Factory接受两个参数group
和weight
(一个int)。权重是按组计算的。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: weight_high
<span style="color:#7f007f"> uri</span>: https://weighthigh.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 8
<span style="color:#7f007f"> - id</span>: weight_low
<span style="color:#7f007f"> uri</span>: https://weightlow.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Weight</span>=group1<span style="color:#7f0055"><strong>,</strong></span> 2</span></span></span>
此路由会将约80%的流量转发到https://weighthigh.org,并将约20%的流量转发到https://weighlow.org
114.11.1修改解析远程地址的方式
默认情况下,RemoteAddr路由谓词工厂使用传入请求中的远程地址。如果Spring Cloud网关位于代理层后面,则此地址可能与实际的客户端IP地址不匹配。
您可以通过设置自定义RemoteAddressResolver
来自定义解析远程地址的方式。Spring Cloud网关带有一个基于X-Forwarded-For标头 XForwardedRemoteAddressResolver
的非默认远程地址解析器。
XForwardedRemoteAddressResolver
有两个静态构造方法,它们采用不同的安全性方法:
XForwardedRemoteAddressResolver::trustAll
返回一个RemoteAddressResolver
,该地址始终使用在X-Forwarded-For
标头中找到的第一个IP地址。这种方法容易受到欺骗,因为恶意客户端可能会为X-Forwarded-For
设置一个初始值,该初始值将被解析程序接受。
XForwardedRemoteAddressResolver::maxTrustedIndex
获取一个索引,该索引与在Spring Cloud网关前面运行的受信任基础结构的数量相关。例如,如果Spring Cloud网关只能通过HAProxy访问,则应使用值1。如果在访问Spring Cloud网关之前需要两跳可信基础结构,则应使用值2。
给定以下标头值:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3</span></span></span>
下面的maxTrustedIndex
值将产生以下远程地址。
maxTrustedIndex | 结果 |
---|---|
[ | (invalid, |
1 | 0.0.0.3 |
2 | 0.0.0.2 |
3 | 0.0.0.1 |
[4, | 0.0.0.1 |
使用Java配置:
GatewayConfig.java
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);
...
.route(<span style="color:#2a00ff">"direct-route"</span>,
r -> r.remoteAddr(<span style="color:#2a00ff">"10.1.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>)
.uri(<span style="color:#2a00ff">"https://downstream1"</span>)
.route(<span style="color:#2a00ff">"proxied-route"</span>,
r -> r.remoteAddr(resolver, <span style="color:#2a00ff">"10.10.1.1"</span>, <span style="color:#2a00ff">"10.10.1.1/24"</span>)
.uri(<span style="color:#2a00ff">"https://downstream2"</span>)
)</span></span></span>
115.网关过滤器工厂
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。路由过滤器适用于特定路由。Spring Cloud网关包括许多内置的GatewayFilter工厂。
注意有关如何使用以下任何过滤器的更多详细示例,请查看单元测试。
115.1 AddRequestHeader GatewayFilter工厂
AddRequestHeader
GatewayFilter工厂采用name
和value
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
这会将X-Request-Foo:Bar
标头添加到所有匹配请求的下游请求标头中。
AddRequestHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.2 AddRequestParameter GatewayFilter工厂
AddRequestParameter
GatewayFilter工厂采用name
和value
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_parameter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar</span></span></span>
这会将foo=bar
添加到所有匹配请求的下游请求的查询字符串中。
AddRequestParameter知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_request_parameter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddRequestParameter</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.3 AddResponseHeader GatewayFilter工厂
AddResponseHeader
GatewayFilter工厂采用name
和value
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
这会将X-Response-Foo:Bar
标头添加到所有匹配请求的下游响应的标头中。
AddResponseHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: add_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.4 DedupeResponseHeader GatewayFilter工厂
DedupeResponseHeader
GatewayFilter工厂采用name
参数和可选的strategy
参数。name
可以包含标题名称列表,以空格分隔。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: dedupe_response_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - DedupeResponseHeader</span>=Access-Control-Allow-Credentials Access-Control-Allow-Origin</span></span></span>
在网关CORS逻辑和下游逻辑都将它们添加的情况下,这将删除Access-Control-Allow-Credentials
和Access-Control-Allow-Origin
响应头的重复值。
DedupeResponseHeader过滤器还接受可选的strategy
参数。可接受的值为RETAIN_FIRST
(默认值),RETAIN_LAST
和RETAIN_UNIQUE
。
115.5 Hystrix GatewayFilter工厂
Hystrix是Netflix的一个库,它实现了断路器模式。Hystrix
GatewayFilter允许您将断路器引入网关路由,保护服务免受级联故障的影响,并允许您在下游故障的情况下提供后备响应。
要在您的项目中启用Hystrix
GatewayFilters,请添加对Spring Cloud Netflix中的 spring-cloud-starter-netflix-hystrix
的依赖。
Hystrix
GatewayFilter工厂需要一个name
参数,它是HystrixCommand
的名称。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: hystrix_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - Hystrix</span>=myCommandName</span></span></span>
这会将其余过滤器包装在命令名称为myCommandName
的HystrixCommand
中。
Hystrix过滤器还可以接受可选的fallbackUri
参数。当前,仅支持forward:
计划的URI。如果调用了后备,则请求将被转发到与URI相匹配的控制器。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: hystrix_route
<span style="color:#7f007f"> uri</span>: lb://backing-service:8088
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/consumingserviceendpoint
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fallbackcmd
<span style="color:#7f007f"> fallbackUri</span>: forward:/incaseoffailureusethis
<span style="color:#7f007f"> - RewritePath</span>=/consumingserviceendpoint<span style="color:#7f0055"><strong>,</strong></span> /backingserviceendpoint</span></span></span>
调用Hystrix后备广告时,它将转发到/incaseoffailureusethis
URI。请注意,此示例还通过目标URI上的lb
前缀演示了(可选)Spring Cloud Netflix Ribbon负载均衡。
主要方案是将fallbackUri
用于网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: ingredients
<span style="color:#7f007f"> uri</span>: lb://ingredients
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=//ingredients/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fetchIngredients
<span style="color:#7f007f"> fallbackUri</span>: forward:/fallback
<span style="color:#7f007f"> - id</span>: ingredients-fallback
<span style="color:#7f007f"> uri</span>: http://localhost:9994
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/fallback</span></span></span>
在此示例中,网关应用程序中没有fallback
端点或处理程序,但是,另一个应用程序中没有fallback
端点或处理程序,已在http://localhost:9994
下注册。
如果将请求转发到后备,则Hystrix网关过滤器还会提供引起请求的Throwable
。它作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR
属性添加到ServerWebExchange
中,可以在网关应用程序中处理后备时使用。
对于外部控制器/处理程序方案,可以添加带有异常详细信息的标头。您可以在FallbackHeaders GatewayFilter Factory部分中找到有关它的更多信息。
Hystrix设置(例如超时)可以使用全局默认值进行配置,也可以使用Hystrix Wiki中所述的应用程序属性在逐条路由的基础上进行配置。
要为上述示例路由设置5秒超时,将使用以下配置:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds</span>: 5000</span></span></span>
115.6 FallbackHeaders GatewayFilter工厂
FallbackHeaders
工厂允许您在转发到外部应用程序中的fallbackUri
的请求的标头中添加Hystrix执行异常详细信息,例如以下情况:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: ingredients
<span style="color:#7f007f"> uri</span>: lb://ingredients
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=//ingredients/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Hystrix
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> name</span>: fetchIngredients
<span style="color:#7f007f"> fallbackUri</span>: forward:/fallback
<span style="color:#7f007f"> - id</span>: ingredients-fallback
<span style="color:#7f007f"> uri</span>: http://localhost:9994
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/fallback
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: FallbackHeaders
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> executionExceptionTypeHeaderName</span>: Test-Header</span></span></span>
在此示例中,在运行HystrixCommand
时发生执行异常之后,该请求将转发到fallback
端点或运行在localhost:9994
上的应用程序中的处理程序。具有异常类型,消息和-if available-根本原因异常类型和消息的标头将由FallbackHeaders
过滤器添加到该请求。
通过设置下面列出的参数的值及其默认值,可以在配置中覆盖标头的名称:
executionExceptionTypeHeaderName
("Execution-Exception-Type"
)executionExceptionMessageHeaderName
("Execution-Exception-Message"
)rootCauseExceptionTypeHeaderName
("Root-Cause-Exception-Type"
)rootCauseExceptionMessageHeaderName
("Root-Cause-Exception-Message"
)
您可以在Hystrix GatewayFilter工厂部分中找到有关Hystrix与Gateway一起工作的更多信息。
115.7 MapRequestHeader GatewayFilter工厂
MapRequestHeader
GatewayFilter要素采用'fromHeader'和'toHeader'参数。它创建一个新的命名标头(toHeader),并从传入的HTTP请求中从现有的命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器不起作用。如果新的命名标头已经存在,则将使用新值扩充其值。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: map_request_header_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - MapRequestHeader</span>=Bar<span style="color:#7f0055"><strong>,</strong></span> X-Request-Foo</span></span></span>
这会将X-Request-Foo:<values>
标头添加到下游请求中,并带有来自传入的HTTP请求Bar
标头的更新值。
115.8 PrefixPath GatewayFilter工厂
PrefixPath
GatewayFilter工厂采用单个prefix
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: prefixpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - PrefixPath</span>=/mypath</span></span></span>
这会将/mypath
作为所有匹配请求的路径的前缀。因此,对/hello
的请求将被发送到/mypath/hello
。
115.9 PreserveHostHeader GatewayFilter工厂
PreserveHostHeader
GatewayFilter工厂没有参数。该过滤器设置请求属性,路由过滤器将检查该请求属性以确定是否应发送原始主机头,而不是由HTTP客户端确定的主机头。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: preserve_host_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
- PreserveHostHeader</span></span></span>
115.10 RequestRateLimiter GatewayFilter工厂
RequestRateLimiter
GatewayFilter工厂使用RateLimiter
实现来确定是否允许继续当前请求。如果不是,则返回状态HTTP 429 - Too Many Requests
(默认)。
该过滤器采用一个可选的keyResolver
参数和特定于速率限制器的参数(请参见下文)。
keyResolver
是实现KeyResolver
接口的bean。在配置中,使用SpEL通过名称引用bean。#{@myKeyResolver}
是引用名称为myKeyResolver
的bean的SpEL表达式。
KeyResolver.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}</span></span></span>
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-status-code
属性来调整此行为。
无法通过“快捷方式”符号配置RequestRateLimiter。以下示例无效 |
application.properties。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"># INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}</span></span></span>
115.10.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
,可以允许临时突发。在这种情况下,速率限制器需要在突发之间间隔一段时间(根据replenishRate
),因为2个连续的突发将导致请求丢失(HTTP 429 - Too Many Requests
)。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: requestratelimiter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestRateLimiter
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> redis-rate-limiter.replenishRate</span>: 10
<span style="color:#7f007f"> redis-rate-limiter.burstCapacity</span>: 20</span></span></span>
Config.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
KeyResolver userKeyResolver() {
<span style="color:#7f0055"><strong>return</strong></span> exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst(<span style="color:#2a00ff">"user"</span>));
}</span></span></span>
这定义了每个用户10的请求速率限制。允许20个突发,但是下一秒只有10个请求可用。KeyResolver
是一个简单的参数,它获取user
请求参数(注意:不建议在生产中使用)。
速率限制器也可以定义为实现RateLimiter
接口的bean。在配置中,使用SpEL通过名称引用bean。#{@myRateLimiter}
是一个SpEL表达式,引用名称为myRateLimiter
的bean。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: requestratelimiter_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestRateLimiter
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> rate-limiter</span>: <span style="color:#2a00ff">"#{@myRateLimiter}"</span>
<span style="color:#7f007f"> key-resolver</span>: <span style="color:#2a00ff">"#{@userKeyResolver}"</span></span></span></span>
115.11重定向到GatewayFilter工厂
RedirectTo
GatewayFilter工厂采用一个status
和一个url
参数。状态应该是300系列重定向http代码,例如301。URL应该是有效的URL。这将是Location
标头的值。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: prefixpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RedirectTo</span>=302<span style="color:#7f0055"><strong>,</strong></span> https://acme.org</span></span></span>
这将发送带有Location:https://acme.org
标头的状态302以执行重定向。
115.12 RemoveRequestHeader GatewayFilter工厂
RemoveRequestHeader
GatewayFilter工厂采用一个name
参数。它是要删除的标题的名称。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: removerequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RemoveRequestHeader</span>=X-Request-Foo</span></span></span>
这将删除X-Request-Foo
标头,然后将其发送到下游。
115.13 RemoveResponseHeader GatewayFilter工厂
RemoveResponseHeader
GatewayFilter工厂采用一个name
参数。它是要删除的标题的名称。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: removeresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RemoveResponseHeader</span>=X-Response-Foo</span></span></span>
这会将X-Response-Foo
标头从响应中删除,然后将其返回到网关客户端。
要删除任何类型的敏感标头,应为可能需要的任何路由配置此过滤器。此外,您可以使用spring.cloud.gateway.default-filters
一次配置此过滤器,并将其应用于所有路由。
115.14 RewritePath GatewayFilter工厂
RewritePath
GatewayFilter工厂采用路径regexp
参数和replacement
参数。这使用Java正则表达式提供了一种灵活的方式来重写请求路径。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewritepath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewritePath</span>=/foo(?<segment>/?.*)<span style="color:#7f0055"><strong>,</strong></span> $\{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
对于/foo/bar
的请求路径,这将在发出下游请求之前将路径设置为/bar
。请注意,由于YAML规范,$\
被$
所取代。
115.15 RewriteLocationResponseHeader GatewayFilter工厂
RewriteLocationResponseHeader
GatewayFilter工厂通常会修改Location
响应标头的值,以摆脱后端特定的详细信息。它需要stripVersionMode
,locationHeaderName
,hostValue
和protocolsRegex
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewritelocationresponseheader_route
<span style="color:#7f007f"> uri</span>: http://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewriteLocationResponseHeader</span>=AS_IN_REQUEST<span style="color:#7f0055"><strong>,</strong></span> Location<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span></span></span></span>
例如,对于请求POST https://api.example.com/some/object/name
,Location
响应标头值https://object-service.prod.example.net/v2/some/object/id
将被重写为https://api.example.com/some/object/id
。
参数stripVersionMode
具有以下可能的值:NEVER_STRIP
,AS_IN_REQUEST
(默认),ALWAYS_STRIP
。
NEVER_STRIP
-即使原始请求路径不包含版本,也不会剥离版本AS_IN_REQUEST
-仅当原始请求路径不包含版本时,版本才会被剥离ALWAYS_STRIP
-即使原始请求路径包含版本,也会剥离版本
参数hostValue
(如果提供)将用于替换响应Location
标头中的host:port
部分。如果未提供,将使用Host
请求标头的值。
参数protocolsRegex
必须是有效的正则表达式String
,协议名称将与之匹配。如果不匹配,过滤器将不执行任何操作。默认值为http|https|ftp|ftps
。
115.16 RewriteResponseHeader GatewayFilter工厂
RewriteResponseHeader
GatewayFilter工厂采用name
,regexp
和replacement
参数。它使用Java正则表达式以灵活的方式重写响应标头值。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: rewriteresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - RewriteResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> <span style="color:#7f0055"><strong>,</strong></span> password=[^&]+<span style="color:#7f0055"><strong>,</strong></span> password=***</span></span></span>
对于标头值为/42?user=ford&password=omg!what&flag=true
,在发出下游请求后它将被设置为/42?user=ford&password=***&flag=true
。由于YAML规范,请使用$\
来表示$
。
115.17 SaveSession GatewayFilter工厂
在向下游转发呼叫之前,SaveSession GatewayFilter工厂强制执行WebSession::save
操作。这在将Spring Session之类的内容用于惰性数据存储并且需要确保在进行转接呼叫之前已保存会话状态时特别有用。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: save_session
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/**
<span style="color:#7f007f"> filters</span>:
- SaveSession</span></span></span>
如果您将Spring Security与Spring Session 集成在一起,并且想要确保安全性详细信息已转发到远程进程,则至关重要。
115.18 SecureHeaders GatewayFilter工厂
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
名称空间中设置适当的属性:
Property进行更改:
xss-protection-header
strict-transport-security
frame-options
content-type-options
referrer-policy
content-security-policy
download-options
permitted-cross-domain-policies
要禁用默认值,请使用逗号分隔值设置属性spring.cloud.gateway.filter.secure-headers.disable
。
需要使用小写和安全标头的全名。 |
可以使用以下值:
x-xss-protection
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=x-frame-options,strict-transport-security
115.19 SetPath GatewayFilter工厂
SetPath
GatewayFilter工厂采用路径template
参数。通过允许路径的模板段,它提供了一种操作请求路径的简单方法。这将使用Spring Framework中的uri模板。允许多个匹配段。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setpath_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/foo/{segment<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetPath</span>=/{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
对于/foo/bar
的请求路径,这将在发出下游请求之前将路径设置为/bar
。
115.20 SetRequestHeader GatewayFilter工厂
SetRequestHeader
GatewayFilter工厂采用name
和value
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setrequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetRequestHeader</span>=X-Request-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
该GatewayFilter用给定的名称替换所有标头,而不是添加。因此,如果下游服务器响应X-Request-Foo:1234
,则将其替换为X-Request-Foo:Bar
,下游服务将收到此信息。
SetRequestHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setrequestheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetRequestHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.21 SetResponseHeader GatewayFilter工厂
SetResponseHeader
GatewayFilter工厂采用name
和value
参数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetResponseHeader</span>=X-Response-Foo<span style="color:#7f0055"><strong>,</strong></span> Bar</span></span></span>
该GatewayFilter用给定的名称替换所有标头,而不是添加。因此,如果下游服务器以X-Response-Foo:1234
响应,则将其替换为X-Response-Foo:Bar
,这是网关客户端将收到的内容。
SetResponseHeader知道用于匹配路径或主机的URI变量。URI变量可用于该值,并将在运行时扩展。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setresponseheader_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>: {segment}.myhost.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetResponseHeader</span>=foo<span style="color:#7f0055"><strong>,</strong></span> bar-{segment<span style="color:#7f0055"><strong>}</strong></span></span></span></span>
115.22 SetStatus GatewayFilter工厂
SetStatus
GatewayFilter工厂采用单个status
参数。它必须是有效的Spring HttpStatus
。它可以是整数值404
,也可以是枚举NOT_FOUND
的字符串表示形式。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setstatusstring_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=BAD_REQUEST
<span style="color:#7f007f"> - id</span>: setstatusint_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=401</span></span></span>
无论哪种情况,响应的HTTP状态都将设置为401。
115.23 StripPrefix GatewayFilter工厂
StripPrefix GatewayFilter工厂采用一个参数parts
。parts
参数指示在向下游发送请求之前,要从请求中剥离的路径中的零件数。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: nameRoot
<span style="color:#7f007f"> uri</span>: http://nameservice
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/name/**
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - StripPrefix</span>=2</span></span></span>
通过网关发送到/name/bar/foo
的请求时,对nameservice
的请求将类似于http://nameservice/foo
。
115.24重试GatewayFilter工厂
Retry
GatewayFilter Factory支持以下参数集:
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
计算退避。
如果启用了Retry
过滤器,则会配置以下默认值:
retries
-3次series
— 5XX系列methods
— GET方法exceptions
-IOException
和TimeoutException
backoff
-已禁用
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: retry_test
<span style="color:#7f007f"> uri</span>: http://localhost:8080/flakey
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Host</span>=*.retry.com
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: Retry
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> retries</span>: 3
<span style="color:#7f007f"> statuses</span>: BAD_GATEWAY
<span style="color:#7f007f"> methods</span>: GET,POST
<span style="color:#7f007f"> backoff</span>:
<span style="color:#7f007f"> firstBackoff</span>: 10ms
<span style="color:#7f007f"> maxBackoff</span>: 50ms
<span style="color:#7f007f"> factor</span>: 2
<span style="color:#7f007f"> basedOnPreviousValue</span>: <span style="color:#7f0055"><strong>false</strong></span></span></span></span>
当使用带有 |
当将重试过滤器与任何具有主体的HTTP方法一起使用时,主体将被缓存,并且网关将受到内存的限制。正文被缓存在 |
115.25 RequestSize GatewayFilter工厂
当请求大小大于允许的限制时,RequestSize
GatewayFilter工厂可以限制请求到达下游服务。过滤器采用maxSize
参数,该参数是请求的允许大小限制。maxSize is a `DataSize
类型,因此值可以定义为数字,后跟可选的DataUnit
后缀,例如'KB'或'MB'。字节的默认值为“ B”。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: request_size_route
<span style="color:#7f007f"> uri</span>: http://localhost:8080/upload
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/upload
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: RequestSize
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> maxSize</span>: 5000000</span></span></span>
当请求因大小而被拒绝时,RequestSize GatewayFilter Factory将响应状态设置为413 Payload Too Large
,并带有一个附加报头errorMessage
。以下是此类errorMessage
的示例。
errorMessage
: Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
如果未在路由定义中作为过滤器参数提供,则默认请求大小将设置为5 MB。 |
115.26修改请求正文GatewayFilter工厂
该过滤器被认为是BETA,API将来可能会更改
ModifyRequestBody
过滤器可用于在网关向下游发送请求主体之前修改请求主体。
只能使用Java DSL配置此过滤器 |
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {
<span style="color:#7f0055"><strong>return</strong></span> builder.routes()
.route(<span style="color:#2a00ff">"rewrite_request_obj"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriterequestobj.org"</span>)
.filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>)
.modifyRequestBody(String.<span style="color:#7f0055"><strong>class</strong></span>, Hello.<span style="color:#7f0055"><strong>class</strong></span>, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> <span style="color:#7f0055"><strong>return</strong></span> Mono.just(<span style="color:#7f0055"><strong>new</strong></span> Hello(s.toUpperCase())))).uri(uri))
.build();
}
<span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Hello {
String message;
<span style="color:#7f0055"><strong>public</strong></span> Hello() { }
<span style="color:#7f0055"><strong>public</strong></span> Hello(String message) {
<span style="color:#7f0055"><strong>this</strong></span>.message = message;
}
<span style="color:#7f0055"><strong>public</strong></span> String getMessage() {
<span style="color:#7f0055"><strong>return</strong></span> message;
}
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>void</strong></span> setMessage(String message) {
<span style="color:#7f0055"><strong>this</strong></span>.message = message;
}
}</span></span></span>
115.27修改响应主体GatewayFilter工厂
该过滤器被认为是BETA,API将来可能会更改
ModifyResponseBody
过滤器可用于在将响应正文发送回客户端之前对其进行修改。
只能使用Java DSL配置此过滤器 |
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator routes(RouteLocatorBuilder builder) {
<span style="color:#7f0055"><strong>return</strong></span> builder.routes()
.route(<span style="color:#2a00ff">"rewrite_response_upper"</span>, r -> r.host(<span style="color:#2a00ff">"*.rewriteresponseupper.org"</span>)
.filters(f -> f.prefixPath(<span style="color:#2a00ff">"/httpbin"</span>)
.modifyResponseBody(String.<span style="color:#7f0055"><strong>class</strong></span>, String.<span style="color:#7f0055"><strong>class</strong></span>,
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
.build();
}</span></span></span>
115.28默认过滤器
如果您要添加过滤器并将其应用于所有路由,则可以使用spring.cloud.gateway.default-filters
。该属性采用过滤器列表
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> default-filters</span>:
<span style="color:#7f007f"> - AddResponseHeader</span>=X-Response-Default-Foo<span style="color:#7f0055"><strong>,</strong></span> Default-Bar
<span style="color:#7f007f"> - PrefixPath</span>=/httpbin</span></span></span>
116.全局过滤器
GlobalFilter
接口具有与GatewayFilter
相同的签名。这些是特殊过滤器,有条件地应用于所有路由。(此接口和用法可能会在将来的里程碑中更改)。
116.1组合的全局过滤器和GatewayFilter排序
当有请求进入(并与路由匹配)时,过滤Web处理程序会将GlobalFilter
的所有实例和GatewayFilter
的所有特定于路由的实例添加到过滤器链中。该组合的过滤器链通过org.springframework.core.Ordered
接口排序,可以通过实现getOrder()
方法进行设置。
由于Spring Cloud网关区分执行过滤器逻辑的“前”阶段和“后”阶段(请参阅:工作原理),因此,具有最高优先级的过滤器将在“前”阶段中处于第一个阶段,在“阶段”中处于最后一个阶段。 “后期”阶段。
ExampleConfiguration.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customFilter() {
<span style="color:#7f0055"><strong>return</strong></span> <span style="color:#7f0055"><strong>new</strong></span> CustomGlobalFilter();
}
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> CustomGlobalFilter <span style="color:#7f0055"><strong>implements</strong></span> GlobalFilter, Ordered {
<em><span style="color:gray">@Override</span></em>
<span style="color:#7f0055"><strong>public</strong></span> Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info(<span style="color:#2a00ff">"custom global filter"</span>);
<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange);
}
<em><span style="color:gray">@Override</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>int</strong></span> getOrder() {
<span style="color:#7f0055"><strong>return</strong></span> -1;
}
}</span></span></span>
116.2转发路由过滤器
ForwardRoutingFilter
在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中寻找URI。如果该网址具有forward
方案(即forward:///localendpoint
),它将使用Spring DispatcherHandler
处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。
116.3 LoadBalancerClient筛选器
LoadBalancerClientFilter
在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中寻找URI。如果该网址具有lb
方案(即lb://myservice
),它将使用Spring Cloud LoadBalancerClient
将名称(上例中为myservice
)解析为实际的主机和端口并替换相同属性中的URI。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
属性,以查看其是否等于lb
,然后应用相同的规则。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: myRoute
<span style="color:#7f007f"> uri</span>: lb://service
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/service/**</span></span></span>
默认情况下,当在 |
从 |
|
116.4 ReactiveLoadBalancerClientFilter
ReactiveLoadBalancerClientFilter
在交换属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
中寻找URI。如果该网址具有lb
方案(即lb://myservice
),它将使用Spring Cloud ReactorLoadBalancer
将名称(上例中为myservice
)解析为实际的主机和端口并替换相同属性中的URI。未经修改的原始URL会附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR
属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
属性,以查看其是否等于lb
,然后应用相同的规则。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: myRoute
<span style="color:#7f007f"> uri</span>: lb://service
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/service/**</span></span></span>
默认情况下,当 |
从 |
116.5网络路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交换属性中的URL具有http
或https
方案,则将运行Netty路由筛选器。它使用Netty HttpClient
发出下游代理请求。响应将放在ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
交换属性中,以供以后的过滤器使用。(有一个实验性WebClientHttpRoutingFilter
,它执行相同的功能,但不需要净值)
116.6 Netty写响应过滤器
如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR
交换属性中有净值HttpClientResponse
,则NettyWriteResponseFilter
将运行。它在所有其他筛选器完成后运行,并将代理响应写回到网关客户端响应。(有一个实验性WebClientWriteResponseFilter
,它执行相同的功能,但不需要净值)
116.7 RouteToRequestUrl过滤器
如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR
交换属性中存在Route
对象,则RouteToRequestUrlFilter
将运行。它基于请求URI创建一个新URI,但使用Route
对象的URI属性进行了更新。新的URI放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交换属性中。
如果URI具有方案前缀(例如lb:ws://serviceid
),则将从URI中剥离lb
方案,并将其放在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR
中,以供以后在过滤器链中使用。
116.8 Websocket路由过滤器
如果位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR
交换属性中的URL具有ws
或wss
方案,则Websocket路由筛选器将运行。它使用Spring Web套接字基础结构向下游转发Websocket请求。
通过在URI前面加上lb
,例如lb:ws://serviceid
,可以实现Websocket的负载均衡。
如果您将SockJS用作常规http的后备,则应配置常规HTTP路由以及Websocket路由。 |
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#3f5f5f"><em># SockJS route</em></span>
<span style="color:#7f007f"> - id</span>: websocket_sockjs_route
<span style="color:#7f007f"> uri</span>: http://localhost:3001
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/websocket/info/**
<span style="color:#3f5f5f"><em># Normal Websocket route</em></span>
<span style="color:#7f007f"> - id</span>: websocket_route
<span style="color:#7f007f"> uri</span>: ws://localhost:3001
<span style="color:#7f007f"> predicates</span>:
<span style="color:#7f007f"> - Path</span>=/websocket/**</span></span></span>
116.9网关指标过滤器
要启用网关度量标准,请添加spring-boot-starter-actuator作为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled
未设置为false
,网关度量过滤器就会运行。该过滤器添加了一个带有以下标记的名为“ gateway.requests”的计时器指标:
routeId
:路线IDrouteUri
:API将被路由到的URIoutcome
:根据HttpStatus.Series分类的结果status
:返回给客户端的请求的Http状态httpStatusCode
:返回给客户端的请求的Http状态httpMethod
:用于请求的Http方法
然后可以从/actuator/metrics/gateway.requests
抓取 这些指标,并且可以轻松地将其与Prometheus集成以创建Grafana 仪表板。
要启用Prometheus端点,请添加micrometer-registry-prometheus作为项目依赖项。 |
116.10将交换标记为已路由
网关路由ServerWebExchange
后,它将通过在交换属性中添加gatewayAlreadyRouted
将该交换标记为“已路由”。将请求标记为已路由后,其他路由筛选器将不会再次路由请求,实质上会跳过该筛选器。您可以使用多种便捷方法将交换标记为已路由,或者检查交换是否已路由。
ServerWebExchangeUtils.isAlreadyRouted
接受ServerWebExchange
对象,并检查其是否已“路由”ServerWebExchangeUtils.setAlreadyRouted
接受ServerWebExchange
对象,并将其标记为“已路由”
117. HttpHeadersFilters
HttpHeadersFilters在向下游发送请求之前(例如,在NettyRoutingFilter
中)已应用于请求。
117.1转发的标题过滤器
Forwarded
标头过滤器创建一个Forwarded
标头,以发送到下游服务。它将当前请求的Host
标头,方案和端口添加到任何现有的Forwarded
标头中。
117.2 RemoveHopByHop标头过滤器
RemoveHopByHop
标头过滤器从转发的请求中删除标头。被删除的头的默认列表来自IETF。
默认删除的标题为:
- 连接
- 活着
- 代理验证
- 代理授权
- TE
- 预告片
- 传输编码
- 升级
要更改此设置,请将spring.cloud.gateway.filter.remove-non-proxy-headers.headers
属性设置为要删除的标头名称列表。
117.3 XForwarded标头过滤器
XForwarded
标头过滤器创建各种X-Forwarded-*
标头,以发送到下游服务。它使用Host
头,当前请求的方案,端口和路径来创建各种头。
可以通过以下布尔属性(默认为true)控制单个标题的创建:
spring.cloud.gateway.x-forwarded.for.enabled
spring.cloud.gateway.x-forwarded.host.enabled
spring.cloud.gateway.x-forwarded.port.enabled
spring.cloud.gateway.x-forwarded.proto.enabled
spring.cloud.gateway.x-forwarded.prefix.enabled
可以通过以下布尔属性(默认为true)控制追加多个标头:
spring.cloud.gateway.x-forwarded.for.append
spring.cloud.gateway.x-forwarded.host.append
spring.cloud.gateway.x-forwarded.port.append
spring.cloud.gateway.x-forwarded.proto.append
spring.cloud.gateway.x-forwarded.prefix.append
118. TLS / SSL
网关可以通过遵循常规的Spring服务器配置来侦听https上的请求。例:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">server</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> enabled</span>: <span style="color:#7f0055"><strong>true</strong></span>
<span style="color:#7f007f"> key-alias</span>: scg
<span style="color:#7f007f"> key-store-password</span>: scg1234
<span style="color:#7f007f"> key-store</span>: classpath:scg-keystore.p12
<span style="color:#7f007f"> key-store-type</span>: PKCS12</span></span></span>
网关路由可以同时路由到http和https后端。如果路由到https后端,则可以使用以下配置将网关配置为信任所有下游证书:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> useInsecureTrustManager</span>: <span style="color:#7f0055"><strong>true</strong></span></span></span></span>
使用不安全的信任管理器不适用于生产。对于生产部署,可以为网关配置一组可以通过以下配置信任的已知证书:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> trustedX509Certificates</span>:
- cert1.pem
- cert2.pem</span></span></span>
如果Spring Cloud网关未配置受信任的证书,则使用默认的信任存储(可以使用系统属性javax.net.ssl.trustStore覆盖)。
118.1 TLS握手
网关维护一个客户端池,该客户端池用于路由到后端。通过https进行通信时,客户端会启动TLS握手。许多超时与此握手相关联。可以配置以下超时(显示默认值):
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> httpclient</span>:
<span style="color:#7f007f"> ssl</span>:
<span style="color:#7f007f"> handshake-timeout-millis</span>: 10000
<span style="color:#7f007f"> close-notify-flush-timeout-millis</span>: 3000
<span style="color:#7f007f"> close-notify-read-timeout-millis</span>: 0</span></span></span>
119.配置
Spring Cloud网关的配置由RouteDefinitionLocator
的集合驱动。
RouteDefinitionLocator.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>interface</strong></span> RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}</span></span></span>
默认情况下,PropertiesRouteDefinitionLocator
使用Spring Boot的@ConfigurationProperties
机制加载属性。
上面的所有配置示例都使用一种快捷方式符号,该快捷方式符号使用位置参数而不是命名参数。以下两个示例是等效的:
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> routes</span>:
<span style="color:#7f007f"> - id</span>: setstatus_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - name</span>: SetStatus
<span style="color:#7f007f"> args</span>:
<span style="color:#7f007f"> status</span>: 401
<span style="color:#7f007f"> - id</span>: setstatusshortcut_route
<span style="color:#7f007f"> uri</span>: https://example.org
<span style="color:#7f007f"> filters</span>:
<span style="color:#7f007f"> - SetStatus</span>=401</span></span></span>
对于网关的某些用法,属性将是足够的,但某些生产用例将受益于从外部源(例如数据库)加载配置。未来的里程碑版本将基于Spring Data Repositories实现RouteDefinitionLocator
实现,例如:Redis,MongoDB和Cassandra。
119.1 Fluent Java Routes API
为了在Java中进行简单的配置,在RouteLocatorBuilder
bean中定义了一个流畅的API。
GatewaySampleApplication.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#3f5f5f"><em>// static imports from GatewayFilters and RoutePredicates</em></span>
<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
<span style="color:#7f0055"><strong>return</strong></span> builder.routes()
.route(r -> r.host(<span style="color:#2a00ff">"**.abc.org"</span>).and().path(<span style="color:#2a00ff">"/image/png"</span>)
.filters(f ->
f.addResponseHeader(<span style="color:#2a00ff">"X-TestHeader"</span>, <span style="color:#2a00ff">"foobar"</span>))
.uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
)
.route(r -> r.path(<span style="color:#2a00ff">"/image/webp"</span>)
.filters(f ->
f.addResponseHeader(<span style="color:#2a00ff">"X-AnotherHeader"</span>, <span style="color:#2a00ff">"baz"</span>))
.uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
)
.route(r -> r.order(-1)
.host(<span style="color:#2a00ff">"**.throttle.org"</span>).and().path(<span style="color:#2a00ff">"/get"</span>)
.filters(f -> f.filter(throttle.apply(1,
1,
10,
TimeUnit.SECONDS)))
.uri(<span style="color:#2a00ff">"http://httpbin.org:80"</span>)
)
.build();
}</span></span></span>
此样式还允许更多自定义谓词断言。RouteDefinitionLocator
beans定义的谓词使用逻辑and
进行组合。通过使用流畅的Java API,您可以在Predicate
类上使用and()
,or()
和negate()
运算符。
119.2 DiscoveryClient路由定义定位器
可以将网关配置为基于在DiscoveryClient
兼容服务注册表中注册的服务来创建路由。
要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true
并确保在类路径上启用了DiscoveryClient
实现(例如Netflix Eureka,Consul或Zookeeper)。
119.2.1为DiscoveryClient路由配置谓词和过滤器
默认情况下,网关为通过DiscoveryClient
创建的路由定义单个谓词和过滤器。
默认谓词是使用模式/serviceId/**
定义的路径谓词,其中serviceId
是DiscoveryClient
中服务的ID。
缺省过滤器是带有正则表达式/serviceId/(?<remaining>.*)
和替换文本/${remaining}
的重写路径过滤器。这只是在将请求发送到下游之前从路径中剥离服务ID。
如果要自定义DiscoveryClient
路由使用的谓词和/或过滤器,可以通过设置spring.cloud.gateway.discovery.locator.predicates[x]
和spring.cloud.gateway.discovery.locator.filters[y]
来实现。这样做时,如果要保留该功能,则需要确保在上面包含默认谓词和过滤器。以下是此示例的示例。
application.properties。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">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}'"</span></span></span>
120. Reactor Netty访问日志
要启用Reactor Netty访问日志,请设置-Dreactor.netty.http.server.accessLogEnabled=true
。(它必须是Java系统Property,而不是Spring Boot属性)。
日志系统可以配置为具有单独的访问日志文件。以下是示例登录配置:
logback.xml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"> <span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"accessLog"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.core.FileAppender"</span><span style="color:#3f7f7f">></span>
<span style="color:#3f7f7f"><file></span>access_log.log<span style="color:#3f7f7f"></file></span>
<span style="color:#3f7f7f"><encoder></span>
<span style="color:#3f7f7f"><pattern></span>%msg%n<span style="color:#3f7f7f"></pattern></span>
<span style="color:#3f7f7f"></encoder></span>
<span style="color:#3f7f7f"></appender></span>
<span style="color:#3f7f7f"><appender</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"async"</span> <span style="color:#7f007f">class</span>=<span style="color:#2a00ff">"ch.qos.logback.classic.AsyncAppender"</span><span style="color:#3f7f7f">></span>
<span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"accessLog"</span><span style="color:#3f7f7f"> /></span>
<span style="color:#3f7f7f"></appender></span>
<span style="color:#3f7f7f"><logger</span> <span style="color:#7f007f">name</span>=<span style="color:#2a00ff">"reactor.netty.http.server.AccessLog"</span> <span style="color:#7f007f">level</span>=<span style="color:#2a00ff">"INFO"</span> <span style="color:#7f007f">additivity</span>=<span style="color:#2a00ff">"false"</span><span style="color:#3f7f7f">></span>
<span style="color:#3f7f7f"><appender-ref</span> <span style="color:#7f007f">ref</span>=<span style="color:#2a00ff">"async"</span><span style="color:#3f7f7f">/></span>
<span style="color:#3f7f7f"></logger></span></span></span></span>
121. CORS配置
可以将网关配置为控制CORS行为。“全局” CORS配置是URL模式到Spring Framework CorsConfiguration的映射。
application.yml。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring</span>:
<span style="color:#7f007f"> cloud</span>:
<span style="color:#7f007f"> gateway</span>:
<span style="color:#7f007f"> globalcors</span>:
<span style="color:#7f007f"> corsConfigurations</span>:
<span style="color:#7f007f"> '[/**]'</span>:
<span style="color:#7f007f"> allowedOrigins</span>: <span style="color:#2a00ff">"https://docs.spring.io"</span>
<span style="color:#7f007f"> allowedMethods</span>:
- GET</span></span></span>
在上面的示例中,对于所有GET请求的路径,来自docs.spring.io的请求都将允许CORS请求。
要为未被某些网关路由谓词处理的请求提供相同的CORS配置,请将属性spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping
设置为true。当尝试支持CORS预检请求并且您的路由谓词未评估为true时,这很有用,因为http方法为options
。
122.执行器API
/gateway
执行器端点允许监视Spring Cloud Gateway应用程序并与之交互。为了可远程访问,必须在应用程序属性中通过HTTP或JMX 启用和公开端点。
application.properties。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">management.endpoint.gateway.enabled</span>=true <span style="color:#3f5f5f"><em># default value</em></span>
<span style="color:#7f007f">management.endpoints.web.exposure.include</span>=gateway</span></span></span>
122.1详细执行器格式
一种新的,更详细的格式已添加到网关。这为每个路由增加了更多细节,从而允许查看与每个路由关联的谓词和过滤器以及任何可用的配置。
/actuator/gateway/routes
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>[</strong></span>
<span style="color:#7f0055"><strong>{</strong></span>
<span style="color:#2a00ff">"predicate"</span>: <span style="color:#2a00ff">"(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)"</span><span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"route_id"</span>: <span style="color:#2a00ff">"add_request_header_test"</span><span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"filters"</span>: <span style="color:#7f0055"><strong>[</strong></span>
<span style="color:#2a00ff">"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]"</span><span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"[[PrefixPath prefix = '/httpbin'], order = 2]"</span>
]<span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"uri"</span>: <span style="color:#2a00ff">"lb://testservice"</span><span style="color:#7f0055"><strong>,</strong></span>
<span style="color:#2a00ff">"order"</span>: 0
<span style="color:#7f0055"><strong>}</strong></span>
<span style="color:#7f0055"><strong>]</strong></span></span></span></span>
要启用此功能,请设置以下属性:
application.properties。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f007f">spring.cloud.gateway.actuator.verbose.enabled</span>=true</span></span></span>
在将来的版本中,该默认值为true。
122.2检索路由过滤器
122.2.1全局过滤器
要检索应用于所有路由的全局过滤器,请向/actuator/gateway/globalfilters
发出GET
请求。产生的响应类似于以下内容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
"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
}</span></span></span>
该响应包含适当的全局过滤器的详细信息。为每个全局过滤器提供过滤器对象的字符串表示形式(例如org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5
)和过滤器链中的相应顺序。
122.2.2路由过滤器
要检索应用于路由的GatewayFilter工厂,请向/actuator/gateway/routefilters
发出GET
请求。产生的响应类似于以下内容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}</span></span></span>
该响应包含应用于任何特定路由的GatewayFilter工厂的详细信息。为每个工厂提供相应对象的字符串表示形式(例如[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]
)。请注意,null
值是由于端点控制器的实现不完整而导致的,因为它试图设置对象在过滤器链中的顺序,该顺序不适用于GatewayFilter工厂对象。
122.3刷新路由缓存
要清除路由缓存,请向/actuator/gateway/refresh
发出POST
请求。该请求返回200,但没有响应主体。
122.4检索网关中定义的路由
要检索网关中定义的路由,请向/actuator/gateway/routes
发出GET
请求。产生的响应类似于以下内容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">[{
"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
}]</span></span></span>
该响应包含网关中定义的所有路由的详细信息。下表描述了响应的每个元素(即路线)的结构。
路径 | 类型 | 描述 |
---|---|---|
| String | The route id. |
| Object | The route predicate. |
| Array | The GatewayFilter factories applied to the route. |
| Number | The route order. |
122.5检索有关特定路线的信息
要检索有关一条路线的信息,请向/actuator/gateway/routes/{id}
发送一个GET
请求(例如/actuator/gateway/routes/first_route
)。产生的响应类似于以下内容:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8">{
"id": "first_route",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"/first"}
}],
"filters": [],
"uri": "https://www.uri-destination.org",
"order": 0
}]</span></span></span>
下表描述了响应的结构。
路径 | 类型 | 描述 |
---|---|---|
| String | The route id. |
| Array | The collection of route predicates. Each item defines the name and the arguments of a given predicate. |
| Array | The collection of filters applied to the route. |
| String | The destination URI of the route. |
| Number | The route order. |
122.6创建和删除特定路线
要创建路由,请使用指定路由字段的JSON正文向/gateway/routes/{id_route_to_create}
发出POST
请求(请参见上一小节)。
要删除路由,请向/gateway/routes/{id_route_to_delete}
发出DELETE
请求。
122.7概述:所有端点的列表
下表总结了Spring Cloud网关执行器端点。请注意,每个端点都有/actuator/gateway
作为基本路径。
ID | HTTP方法 | 描述 |
---|---|---|
| GET | Displays the list of global filters applied to the routes. |
| GET | Displays the list of GatewayFilter factories applied to a particular route. |
| POST | Clears the routes cache. |
| GET | Displays the list of routes defined in the gateway. |
| GET | Displays information about a particular route. |
| POST | Add a new route to the gateway. |
| DELETE | Remove an existing route from the gateway. |
123.故障排除
123.1日志级别
以下是一些有用的记录器,它们包含DEBUG
和TRACE
级别的有价值的故障排除信息。
org.springframework.cloud.gateway
org.springframework.http.server.reactive
org.springframework.web.reactive
org.springframework.boot.autoconfigure.web
reactor.netty
redisratelimiter
123.2窃听
Reactor Netty HttpClient
和HttpServer
可以启用窃听功能。与将reactor.netty
日志级别设置为DEBUG
或TRACE
结合使用时,将允许记录信息,例如通过网络发送和接收的标头和正文。要启用此功能,请分别为HttpServer
和HttpClient
设置spring.cloud.gateway.httpserver.wiretap=true
和/或spring.cloud.gateway.httpclient.wiretap=true
。
124.开发人员指南
这些是编写网关的某些自定义组件的基本指南。
124.1编写自定义路由谓词工厂
为了编写路由谓词,您将需要实现RoutePredicateFactory
。您可以扩展名为AbstractRoutePredicateFactory
的抽象类。
MyRoutePredicateFactory.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> MyRoutePredicateFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> {
<span style="color:#7f0055"><strong>public</strong></span> MyRoutePredicateFactory() {
<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
}
<em><span style="color:gray">@Override</span></em>
<span style="color:#7f0055"><strong>public</strong></span> Predicate<ServerWebExchange> apply(Config config) {
<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
<span style="color:#7f0055"><strong>return</strong></span> exchange -> {
<span style="color:#3f5f5f"><em>//grab the request</em></span>
ServerHttpRequest request = exchange.getRequest();
<span style="color:#3f5f5f"><em>//take information from the request to see if it</em></span>
<span style="color:#3f5f5f"><em>//matches configuration.</em></span>
<span style="color:#7f0055"><strong>return</strong></span> matches(config, request);
};
}
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
}
}</span></span></span>
124.2编写自定义GatewayFilter工厂
为了编写GatewayFilter,您将需要实现GatewayFilterFactory
。您可以扩展名为AbstractGatewayFilterFactory
的抽象类。
PreGatewayFilterFactory.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PreGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> {
<span style="color:#7f0055"><strong>public</strong></span> PreGatewayFilterFactory() {
<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
}
<em><span style="color:gray">@Override</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {
<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {
<span style="color:#3f5f5f"><em>//If you want to build a "pre" filter you need to manipulate the</em></span>
<span style="color:#3f5f5f"><em>//request before calling chain.filter</em></span>
ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
<span style="color:#3f5f5f"><em>//use builder to manipulate the request</em></span>
<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange.mutate().request(request).build());
};
}
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
}
}</span></span></span>
PostGatewayFilterFactory.java。
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> PostGatewayFilterFactory <span style="color:#7f0055"><strong>extends</strong></span> AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> {
<span style="color:#7f0055"><strong>public</strong></span> PostGatewayFilterFactory() {
<span style="color:#7f0055"><strong>super</strong></span>(Config.<span style="color:#7f0055"><strong>class</strong></span>);
}
<em><span style="color:gray">@Override</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GatewayFilter apply(Config config) {
<span style="color:#3f5f5f"><em>// grab configuration from Config object</em></span>
<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> {
<span style="color:#7f0055"><strong>return</strong></span> chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
<span style="color:#3f5f5f"><em>//Manipulate the response in some way</em></span>
}));
};
}
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>static</strong></span> <span style="color:#7f0055"><strong>class</strong></span> Config {
<span style="color:#3f5f5f"><em>//Put the configuration properties for your filter here</em></span>
}
}</span></span></span>
124.3编写自定义全局过滤器
为了编写自定义全局过滤器,您将需要实现GlobalFilter
接口。这会将过滤器应用于所有请求。
如何分别设置全局前置和后置过滤器的示例
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalFilter() {
<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> exchange.getPrincipal()
.map(Principal::getName)
.defaultIfEmpty(<span style="color:#2a00ff">"Default User"</span>)
.map(userName -> {
<span style="color:#3f5f5f"><em>//adds header to proxied request</em></span>
exchange.getRequest().mutate().header(<span style="color:#2a00ff">"CUSTOM-REQUEST-HEADER"</span>, userName).build();
<span style="color:#7f0055"><strong>return</strong></span> exchange;
})
.flatMap(chain::filter);
}
<em><span style="color:gray">@Bean</span></em>
<span style="color:#7f0055"><strong>public</strong></span> GlobalFilter customGlobalPostFilter() {
<span style="color:#7f0055"><strong>return</strong></span> (exchange, chain) -> chain.filter(exchange)
.then(Mono.just(exchange))
.map(serverWebExchange -> {
<span style="color:#3f5f5f"><em>//adds header to response</em></span>
serverWebExchange.getResponse().getHeaders().set(<span style="color:#2a00ff">"CUSTOM-RESPONSE-HEADER"</span>,
HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? <span style="color:#2a00ff">"It worked"</span>: <span style="color:#2a00ff">"It did not work"</span>);
<span style="color:#7f0055"><strong>return</strong></span> serverWebExchange;
})
.then();
}</span></span></span>
125.使用Spring MVC或Webflux构建一个简单的网关
以下描述了替代样式的网关。先前文档的None适用于以下内容。 |
Spring Cloud Gateway提供了一个名为ProxyExchange
的实用程序对象,您可以在常规的Spring web处理程序中将其用作方法参数。它通过镜像HTTP动词的方法支持基本的下游HTTP交换。使用MVC,它还支持通过forward()
方法转发到本地处理程序。要使用ProxyExchange
,只需在类路径中包含正确的模块(spring-cloud-gateway-mvc
或spring-cloud-gateway-webflux
)。
MVC示例(代理对远程服务器下游“ /测试”的请求):
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {
<em><span style="color:gray">@Value("${remote.home}")</span></em>
<span style="color:#7f0055"><strong>private</strong></span> URI home;
<em><span style="color:gray">@GetMapping("/test")</span></em>
<span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();
}
}</span></span></span>
与Webflux相同:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@RestController</span></em>
<em><span style="color:gray">@SpringBootApplication</span></em>
<span style="color:#7f0055"><strong>public</strong></span> <span style="color:#7f0055"><strong>class</strong></span> GatewaySampleApplication {
<em><span style="color:gray">@Value("${remote.home}")</span></em>
<span style="color:#7f0055"><strong>private</strong></span> URI home;
<em><span style="color:gray">@GetMapping("/test")</span></em>
<span style="color:#7f0055"><strong>public</strong></span> Mono<ResponseEntity<?>> proxy(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/image/png"</span>).get();
}
}</span></span></span>
ProxyExchange
上有一些便利的方法可以使处理程序方法发现并增强传入请求的URI路径。例如,您可能希望提取路径的尾随元素以将它们传递到下游:
<span style="color:#333333"><span style="color:#000000"><span style="background-color:#f8f8f8"><em><span style="color:gray">@GetMapping("/proxy/path/**")</span></em>
<span style="color:#7f0055"><strong>public</strong></span> ResponseEntity<?> proxyPath(ProxyExchange<<span style="color:#7f0055"><strong>byte</strong></span>[]> proxy) <span style="color:#7f0055"><strong>throws</strong></span> Exception {
String path = proxy.path(<span style="color:#2a00ff">"/proxy/path/"</span>);
<span style="color:#7f0055"><strong>return</strong></span> proxy.uri(home.toString() + <span style="color:#2a00ff">"/foos/"</span> + path).get();
}</span></span></span>
网关处理程序方法可以使用Spring MVC或Webflux的所有功能。因此,例如,您可以注入请求标头和查询参数,并且可以使用映射批注中的声明来约束传入的请求。有关这些功能的更多详细信息,请参见Spring MVC中的@RequestMapping
文档。
可以使用ProxyExchange
上的header()
方法将标头添加到下游响应中。
您还可以通过将映射器添加到get()
等方法来操纵响应头(以及响应中您喜欢的任何其他内容)。映射器是Function
,它接收传入的ResponseEntity
并将其转换为传出的ResponseEntity
。
为不传递到下游的“敏感”标头(默认情况下为“ cookie”和“授权”)以及“代理”标头(x-forwarded-*
)提供了一流的支持