springcloud-gateway 网关组件中文文档
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=blockStrict-Transport-Security:max-age=631138519X-Frame-Options:DENYX-Content-Type-Options:nosniffReferrer-Policy:no-referrerContent-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:noopenX-Permitted-Cross-Domain-Policies:none
要更改默认值,请在spring.cloud.gateway.filter.secure-headers名称空间中设置适当的属性:
Property进行更改:
xss-protection-headerstrict-transport-securityframe-optionscontent-type-optionsreferrer-policycontent-security-policydownload-optionspermitted-cross-domain-policies
要禁用默认值,请使用逗号分隔值设置属性spring.cloud.gateway.filter.secure-headers.disable。
|
|
| 需要使用小写和安全标头的全名。 |
可以使用以下值:
x-xss-protectionstrict-transport-securityx-frame-optionsx-content-type-optionsreferrer-policycontent-security-policyx-download-optionsx-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和TimeoutExceptionbackoff-已禁用
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.enabledspring.cloud.gateway.x-forwarded.host.enabledspring.cloud.gateway.x-forwarded.port.enabledspring.cloud.gateway.x-forwarded.proto.enabledspring.cloud.gateway.x-forwarded.prefix.enabled
可以通过以下布尔属性(默认为true)控制追加多个标头:
spring.cloud.gateway.x-forwarded.for.appendspring.cloud.gateway.x-forwarded.host.appendspring.cloud.gateway.x-forwarded.port.appendspring.cloud.gateway.x-forwarded.proto.appendspring.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.gatewayorg.springframework.http.server.reactiveorg.springframework.web.reactiveorg.springframework.boot.autoconfigure.webreactor.nettyredisratelimiter
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-*)提供了一流的支持
相关文章:
springcloud-gateway 网关组件中文文档
Spring Cloud网关 Greenwich SR5 该项目提供了一个基于Spring生态系统的API网关,其中包括:Spring 5,Spring Boot 2和项目Reactor。Spring Cloud网关的目的是提供一种简单而有效的方法来路由到API,并向它们提供跨领域的关注&#x…...
Android Gradle开发与应用Gradle详细使用
一、Gradle 基础知识 1. Gradle 构建脚本 Gradle 构建脚本通常使用 Groovy 或 Kotlin DSL 编写。Android 项目中有两个主要的 Gradle 构建脚本: a、项目级构建脚本 (build.gradle 或 build.gradle.kts):位于项目的根目录中,用于配置项目范…...
软件架构的23个基本原则:构建稳健、可扩展的系统
软件架构是任何软件项目成功的关键。良好的架构不仅能够支撑软件的功能实现,还能确保其性能、可维护性、可扩展性和安全性。在软件工程领域,经过多年的研究和实践,已经总结出了许多宝贵的原则和模式,用以指导软件架构的设计。以下…...
江苏省生产经营单位安全管理考核(附答案)
单选题 1.生产经营单位的主要负责人在本单位发生重大生产安全事故后逃匿的,由( )处 15 日以下拘留。 A、公安机关 B、检察机关 C、安全生产监督管理部门正确答案:A 2.据一些资料表明,心跳呼吸停止,在()min内进行抢救,约80%可以救活。 A、1 B、2 C、3正确答案:A 3.拉开闸刀时…...
Kafka第四篇——生产数据总体概括,源码解析分区策略,数据收集器,Sender发送线程,key值
目录 流程图以及总体概述 拦截器 分区器以及分区计算策略 为啥进行分区计算? producer生产者怎么知道有哪些分区? 分区计算 如何自定义实现分区器? 想说的在图里啦!宝宝!💡 编辑 如果key值忘记传递了呢&a…...
二叉树的链式结构
前言 Hello,友友们,小编将继续重新开始数据结构的学习,前面讲解了堆的部分知识,今天将讲解二叉树的链式结构的部分内容。 1.概念回顾与新增 二叉树是一种数据结构,其中每个节点最多有两个子节点,分别是左子节点和右子…...
【STM32】在标准库中使用DMA
1.MDA简介 DMA全称Direct Memory Access,直接存储区访问。 DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和…...
多线程详解
文章目录 多线程创建方式p3一些教程 狂神说 多线程创建方式p3 代码: package com.demo1;//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程/*** 总结:注意,线程开启不一定立即执行,dCPU调度执行*/public class TestThread1 extends Thre…...
软件工程需求之:业务需求与用户需求
在软件开发项目中,"业务需求"和"用户需求"是两个核心概念,它们分别从不同的角度描述了软件应该具备的功能和特性。理解这两个概念的区别对于成功地规划和开发软件至关重要。 业务需求 业务需求主要关注于软件项目如何帮助实现企业…...
Nettyの源码分析
本篇为Netty系列的最后一篇,按照惯例会简单介绍一些Netty相关核心源码。 1、Netty启动源码分析 代码就使用最初的Netty服务器案例,在bind这一行打上断点,观察启动的全过程: 由于某些方法的调用链过深,节约篇幅…...
MySQL远程登录
root是超级管理员,默认情况下,root不能作为远程登录的用户名,远程登录前,需要将登录的数据库在本地登录,修改权限,输入: update user set host % where user root ; 回车键,再输…...
html的作业
目录 作业题目 1.用户注册 A图 B代码 2.工商银行电子汇款单 A图 B代码 3.李白诗词 A图 B代码 4.豆瓣电影 A图 B代码 学习产出: 作业题目 1.用户注册 A图 B代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset&qu…...
【TORCH】查看dataloader里的数据,通过dataloader.dataset或enumerate
文章目录 dataloader.dataset示例代码使用自定义数据集使用 MNIST 数据集 说明 enumerate示例代码说明使用 MNIST 数据集的例子 dataloader.dataset 是的,您可以直接访问 train_loader 的数据集来查看数据,而不必通过 enumerate 遍历数据加载器。可以通…...
KDTree 简单原理与实现
介绍 K-D树是一种二叉树的数据结构,其中每个节点代表一个k维点,可用于组织K维空间中的点,其中K通常是一个非常大的数字。二叉树结构允许对多维空间中的点进行非常有效的搜索,包括最近邻搜索和范围搜索,树中的每个非叶…...
[c++] 可变参数模版
前言 可变参数模板是C11及之后才开始使用,学校的老古董编译器不一定能用 相信大家在刚入门c/c时都接触过printf函数 int printf ( const char * format, ... ); printf用于将数据格式化输出到屏幕上,它的参数非常有意思,可以支持任意数量,任意类型的多参数.而如果我们想实现类…...
QWidget窗口抗锯齿圆角的一个实现方案(支持子控件)2
QWidget窗口抗锯齿圆角的一个实现方案(支持子控件)2 本方案使用了QGraphicsEffect,由于QGraphicsEffect对一些控件会有渲染问题,比如列表、表格等,所以暂时仅作为研究,优先其他方案 在之前的文章中&#…...
数据结构之“队列”(全方位认识)
🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:数据结构 前言 上期博客介绍了” 栈 “这个数据结构,他具有先进后出的特点。本期介绍“ 队列 ”这个数据结构,他具有先进先出的特点。 目录…...
密码学复习
目录 基础 欧拉函数 欧拉函数φ(n)定义 计算方法的技巧 当a=a_1*a_2*……*a_n时 欧拉定理 剩余系 一些超简单密码 维吉尼亚 密钥fox 凯撒(直接偏移) 凯特巴氏(颠倒字母表) 摩斯密码(字母对应电荷线) 希尔(hill)密码 一些攻击 RSA 求uf+vg=1 快速幂模m^…...
【文献解析】一种像素级的激光雷达相机配准方法
大家好呀,我是一个SLAM方向的在读博士,深知SLAM学习过程一路走来的坎坷,也十分感谢各位大佬的优质文章和源码。随着知识的越来越多,越来越细,我准备整理一个自己的激光SLAM学习笔记专栏,从0带大家快速上手激…...
Http 实现请求body体和响应body体的双向压缩方案
目录 一、前言 二、方案一(和http header不进行关联) 二、方案二(和http header进行关联) 三、 客户端支持Accept-Encoding压缩方式,服务器就一定会进行压缩吗? 四、参考 一、前言 有时请求和响应的body体比较大,需要进行压缩,以减少传输的带宽。 二、方案一(和…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
