tokenpocket最新下载链接安装|gateway官网

作者: tokenpocket最新下载链接安装
2024-03-14 01:51:24

Spring Cloud Gateway 中文文档

Spring Cloud Gateway 中文文档

Dark Theme

Spring Cloud Gateway 中文文档

Table of Contents

1. 如何添加 Spring Cloud Gateway

2. 术语表

3. 它是如何工作的

4. 配置Route ,Predicate ,Filter 工厂

4.1. 快捷方式的配置

4.2. 完全展开的参数

5. Route Predicate(路由谓词)工厂

5.1. After

5.2. Before

5.3. Between

5.4. Cookie

5.5. Header

5.6. Host

5.7. Method

5.8. Path

5.9. Query

5.10. RemoteAddr

5.10.1. 修改远程地址(Remote Addresse)的解析方式

5.11. Weight

5.12. XForwarded Remote Addr

6. GatewayFilter 工厂

6.1. AddRequestHeader

6.2. AddRequestHeadersIfNotPresent

6.3. AddRequestParameter

6.4. AddResponseHeader

6.5. CircuitBreaker

6.5.1. 熔断指定的状态码

6.6. CacheRequestBody

6.7. DedupeResponseHeader

6.8. FallbackHeaders

6.9. JsonToGrpc

6.10. LocalResponseCache

6.11. MapRequestHeader

6.12. ModifyRequestBody

6.13. ModifyResponseBody

6.14. PrefixPath

6.15. PreserveHostHeader

6.16. RedirectTo

6.17. RemoveJsonAttributesResponseBody

6.18. RemoveRequestHeader

6.19. RemoveRequestParameter

6.20. RemoveResponseHeader

6.21. RequestHeaderSize

6.22. RequestRateLimiter

6.22.1. Redis RateLimiter

6.23. RewriteLocationResponseHeader

6.24. RewritePath

6.25. RewriteResponseHeader

6.26. SaveSession

6.27. SecureHeaders

6.28. SetPath

6.29. SetRequestHeader

6.30. SetResponseHeader

6.31. SetStatus

6.32. StripPrefix

6.33. Retry

6.34. RequestSize

6.35. SetRequestHostHeader

6.36. TokenRelay

6.37. 默认 Filter

7. 全局 Filter

7.1. GlobalFilter 组合和 GatewayFilter 的顺序

7.2. Gateway Metrics(指标) Filter

7.3. Local Response Cache Filter

7.4. Forward Routing Filter

7.5. Netty Routing Filter

7.6. Netty Write Response Filter

7.7. ReactiveLoadBalancerClientFilter

7.8. RouteToRequestUrl Filter

7.9. Websocket Routing Filter

7.10. 标记 exchange 为已路由

8. HttpHeadersFilter

8.1. Forwarded Headers Filter

8.2. RemoveHopByHop Headers Filter

8.3. XForwarded Headers Filter

9. TLS 和 SSL

9.1. TLS 握手

10. 配置(Configuration)

10.1. RouteDefinition 指标

11. 路由元数据配置

12. Http超时(timeout)配置

12.1. 全局 timeout

12.2. 每个路由的 timeout

12.3. Route 的Fluent式 Java API

12.4. DiscoveryClient 路由服务的注册与发现

12.4.1. 为 DiscoveryClient 路由配置谓词和过滤器

13. Reactor Netty 访问日志

14. CORS 配置

14.1. Global CORS 配置

14.2. 路由的 CORS 配置

15. Actuator API

15.1. 冗长的 Actuator 格式

15.2. 检索路由过滤器

15.2.1. 全局过滤器(Global Filter)

15.2.2. 路由过滤器(Route Filter)

15.3. 刷新路由缓存

15.4. 检索网关中自定义的路由

15.5. 检索指定的路由

15.6. 创建和删除一个指定的路由

15.7. 回顾:所有端点列表

15.8. 在多个网关实例之间共享路由

16. 问题排查

16.1. 日志级别

16.2. Wiretap

17. 开发手册

17.1. 编写自定义路由(Route)谓语(Predicate)工厂

17.2. 编写自定义 GatewayFilter 工厂

17.2.1. 在配置中命名自定义 Filter 和引用

17.3. 编写自定义全局过滤器

18. 通过使用Spring MVC或Webflux构建一个简单的网关

19. AOT 和 原生镜像(Native Image)的支持

20. 配置属性

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

4.0.2-SNAPSHOT

这个项目提供了一个建立在Spring生态系统之上的API网关,包括。Spring 6、Spring Boot 3 和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为其提供跨领域的关注,如:安全、监控/指标和容错。

1. 如何添加 Spring Cloud Gateway

要在你的项目中添加 Spring Cloud Gateway,请使用 group ID 为 org.springframework.cloud,artifact ID 为 spring-cloud-starter-gateway 的starter。请参阅 Spring Cloud项目页面,了解使用当前 Spring Cloud Release Train 设置构建系统的详情。

如果你添加了 starter,但你不希望启用网关,请设置 spring.cloud.gateway.enabled=false。

Spring Cloud Gateway 是建立在 Spring Boot 2.x、 Spring WebFlux 和 Project Reactor之上。因此,你所熟悉的许多同步库(例如Spring Data和Spring Security)和模式在你使用Spring Cloud Gateway时可能不适用。如果你不熟悉这些项目,我们建议你在使用Spring Cloud Gateway之前,先阅读它们的文档,熟悉一些新概念。

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

2. 术语表

Route(路由): 网关的基本构件。它由一个ID、一个目的地URI、一个谓词(Predicate)集合和一个过滤器(Filter)集合定义。如果集合谓词为真,则路由被匹配。

Predicate(谓词): 这是一个 Java 8 Function Predicate。输入类型是 Spring Framework ServerWebExchange。这让你可以在HTTP请求中的任何内容上进行匹配,比如header或查询参数。

Filter(过滤器): 这些是 GatewayFilter 的实例,已经用特定工厂构建。在这里,你可以在发送下游请求之前或之后修改请求和响应。

3. 它是如何工作的

下图提供了一个关于 Spring Cloud Gateway 如何工作的高层次概述。

客户端向 Spring Cloud Gateway 发出请求。如果Gateway处理程序映射确定一个请求与路由相匹配,它将被发送到Gateway Web处理程序。这个处理程序通过一个特定于该请求的过滤器链来运行该请求。过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和之后运行逻辑。所有的 "pre" (前)过滤器逻辑都被执行。然后发出代理请求。在代理请求发出后,"post" (后)过滤器逻辑被运行。

在路由中定义的没有端口的URI,其HTTP和HTTPS URI的默认端口值分别为80和443。

4. 配置Route ,Predicate ,Filter 工厂

有两种方式来配置谓词和过滤器:快捷方式和完全展开的参数。下面的大多数例子都使用快捷方式。

名称和参数名称作为 code 列在每一节的第一或第二句中。参数通常按照快捷方式配置所需的顺序列出。

4.1. 快捷方式的配置

快捷方式配置由过滤器名称(filter name),后面跟一个等号 (=),然后是用逗号 (,) 分隔的参数值。

application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- Cookie=mycookie,mycookievalue

上面的例子定义了 Cookie 路由谓词工厂,有两个参数,cookie 名称, mycookie 和与 mycookievalue 匹配的值。

4.2. 完全展开的参数

完全展开的参数看起来更像标准的yaml配置,有名称/值对。一般来说,会有一个 name key和一个 args key。args key是一个键值对的映射,用于配置谓词或过滤器。

application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- name: Cookie

args:

name: mycookie

regexp: mycookievalue

这就是上面所示的 Cookie 谓词的快捷配置的完整配置。

5. Route Predicate(路由谓词)工厂

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping 基础设施的一部分。Spring Cloud Gateway包括许多内置的路由谓词工厂。所有这些谓词都与HTTP请求的不同属性相匹配。你可以用逻辑 and 语句组合多个路由谓词工厂。

5.1. After

After 路由谓词工厂需要一个参数,即一个日期时间(这是一个java ZonedDateTime)。这个谓词匹配发生在指定日期时间之后的请求。下面的例子配置了一个After路由谓词。

Example 1. application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- After=2017-01-20T17:42:47.789-07:00[America/Denver]

该路由与北美山区时间(丹佛)2017年1月20日17:42之后发出的任何请求相匹配。

5.2. Before

Before 路由谓词工厂只需要一个参数,即 datetime(这是一个java ZonedDateTime)。这个谓词匹配发生在指定 datetime 之前的请求。下面的例子配置了一个Before路由谓词。

Example 2. application.yml

spring:

cloud:

gateway:

routes:

- id: before_route

uri: https://example.org

predicates:

- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

该路由与北美山区时间2017年1月20日17:42(丹佛)之前发出的任何请求相匹配。

5.3. Between

Between 路由谓词工厂需要两个参数,datetime1 和 datetime2,它们是java ZonedDateTime 对象。这个谓词匹配发生在 datetime1 之后和 datetime2 之前的请求。datetime2 的参数必须在 datetime1 之后。下面的例子配置了一个 between 路由谓词。

Example 3. application.yml

spring:

cloud:

gateway:

routes:

- id: between_route

uri: https://example.org

predicates:

- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

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

5.4. Cookie

Cookie 路由谓词工厂接受两个参数,即 cookie name 和一个 regexp(这是一个Java正则表达式)。这个谓词匹配具有给定名称且其值符合正则表达式的cookie。下面的例子配置了一个cookie路由谓词工厂。

Example 4. application.yml

spring:

cloud:

gateway:

routes:

- id: cookie_route

uri: https://example.org

predicates:

- Cookie=chocolate, ch.p

这个路由匹配有一个名为 chocolate 的cookie,其值符合 ch.p 正则表达式的请求。

5.5. Header

Header 路由谓词工厂需要两个参数,header 和一个 regexp(这是一个Java正则表达式)。这个谓词与具有给定名称且其值与正则表达式相匹配的 header 匹配。下面的例子配置了一个 header 路由谓词。

Example 5. application.yml

spring:

cloud:

gateway:

routes:

- id: header_route

uri: https://example.org

predicates:

- Header=X-Request-Id, \d+

如果请求有一个名为 X-Request-Id 的header,其值与 \d+ 正则表达式相匹配(也就是说,它的值是一个或多个数字),则该路由匹配。

5.6. Host

Host 路由谓语工厂接受一个参数:一个主机(Host)名称的 patterns 列表。该pattern是Ant风格的模式,以 . 为分隔符。这个谓词匹配符合该pattern的Host header。下面的例子配置了一个 host 路由谓词。

Example 6. application.yml

spring:

cloud:

gateway:

routes:

- id: host_route

uri: https://example.org

predicates:

- Host=**.somehost.org,**.anotherhost.org

支持URI模板变量(如 {sub}.myhost.org)。

如果请求的 Host header的值为 www.somehost.org 或 beta.somehost.org 或 www.anotherhost.org,则该路由匹配。

这个谓词提取URI模板变量(比如前面例子中定义的 sub)作为名称和值的映射,并将其放在 ServerWebExchange.getAttributes() 中,key值定义在 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后这些值就可以被 GatewayFilter 工厂使用了。

5.7. Method

Method 路由谓词工厂接受一个 methods 参数,它是一个或多个参数:要匹配的HTTP方法。下面的例子配置了一个 method 路由谓词。

Example 7. application.yml

spring:

cloud:

gateway:

routes:

- id: method_route

uri: https://example.org

predicates:

- Method=GET,POST

如果请求方式是 GET 或 POST,则该路由匹配。

5.8. Path

Path 路由谓词工厂需要两个参数:一个Spring PathMatcher patterns 的list和一个可选的flag matchTrailingSlash(默认为 true)。下面的例子配置了一个path路由谓词。

Example 8. application.yml

spring:

cloud:

gateway:

routes:

- id: path_route

uri: https://example.org

predicates:

- Path=/red/{segment},/blue/{segment}

如果请求路径是 /red/1 或 /red/1/ 或 /red/blue 或 /blue/green,则该路由匹配。

如果 matchTrailingSlash 被设置为 false,那么请求路径 /red/1/ 将不会被匹配。

这个谓词提取URI模板变量(比如前面例子中定义的 segment)作为name和value的映射,并把它放在 ServerWebExchange.getAttributes() 中,KEY值定义在 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。然后这些值就可以被 GatewayFilter 工厂使用了。

有一个实用的方法(称为 get),可以使访问这些变量变得更容易。下面的例子显示了如何使用 get 方法。

Map uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);

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

5.9. Query

Query 路由谓词工厂需要两个参数:一个必需的 param 和一个可选的 regexp(这是一个Java正则表达式)。下面的例子配置了一个 query 路由谓词。

Example 9. application.yml

spring:

cloud:

gateway:

routes:

- id: query_route

uri: https://example.org

predicates:

- Query=green

如果请求包含一个 green 的查询参数,前面的路由就会匹配。

application.yml

spring:

cloud:

gateway:

routes:

- id: query_route

uri: https://example.org

predicates:

- Query=red, gree.

如果请求中包含一个 red 的查询参数,其值与 gree. 表达式相匹配,那么路由就会匹配。例如: green 和 greet 。

5.10. RemoteAddr

RemoteAddr 路由谓词工厂接受一个 sources 集合(最小长度为1),它是CIDR注解(IPv4或IPv6)字符串,如 192.168.0.1/16(其中 192.168.0.1 是一个IP地址,16 是一个子网掩码)。下面的例子配置了一个RemoteAddr路由谓词。

Example 10. application.yml

spring:

cloud:

gateway:

routes:

- id: remoteaddr_route

uri: https://example.org

predicates:

- RemoteAddr=192.168.1.1/24

如果请求的远程地址 192.168.1.10,则该路由匹配。

5.10.1. 修改远程地址(Remote Addresse)的解析方式

默认情况下,RemoteAddr路由谓语工厂使用传入请求中的远程地址。如果Spring Cloud Gateway位于代理层后面,这可能与实际的客户IP地址不一致。

你可以通过设置一个自定义的 RemoteAddressResolver 来定制远程地址的解析方式。Spring Cloud Gateway有一个非默认的远程地址解析器,它是基于 X-Forwarded-For Header的,即 XForwardedRemoteAddressResolver。

XForwardedRemoteAddressResolver 有两个静态构造方法,它们对安全问题采取了不同的方法。

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

XForwardedRemoteAddressResolver::maxTrustedIndex 需要一个索引,该索引与在 Spring Cloud Gateway 前面运行的可信基础设施的数量相关。例如,如果 Spring Cloud Gateway 只能通过 HAProxy 访问,那么应使用1的值。如果在Spring Cloud Gateway被访问之前需要经过2个受信任的基础设施,那么应该使用2的值。

请考虑以下 header 值。

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

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

maxTrustedIndex

结果

[Integer.MIN_VALUE,0]

(无效, 初始化时会抛出 IllegalArgumentException 异常)

1

0.0.0.3

2

0.0.0.2

3

0.0.0.1

[4, Integer.MAX_VALUE]

0.0.0.1

下面的例子显示了如何用Java实现同样的配置。

Example 11. GatewayConfig.java

RemoteAddressResolver resolver = XForwardedRemoteAddressResolver

.maxTrustedIndex(1);

...

.route("direct-route",

r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")

.uri("https://downstream1")

.route("proxied-route",

r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")

.uri("https://downstream2")

)

5.11. Weight

Weight 路由谓语工厂需要两个参数:group 和 weight(一个int值)。weight 是按 group 计算的。下面的例子配置了一个 weight 路由谓词。

Example 12. application.yml

spring:

cloud:

gateway:

routes:

- id: weight_high

uri: https://weighthigh.org

predicates:

- Weight=group1, 8

- id: weight_low

uri: https://weightlow.org

predicates:

- Weight=group1, 2

此路由将转发~80%的流量到 weighthigh.org,~20%的流量到 weighlow.org。

5.12. XForwarded Remote Addr

XForwarded Remote Addr 路由谓语工厂接受一个 sources 集合(最长度为 1),这些 sources 是 CIDR注解(IPv4 或 IPv6)字符串,如 192.168.0.1/16(其中 192.168.0.1 是一个 IP 地址,16 是子网掩码)。

这个路由谓词允许根据 X-Forwarded-For 的 HTTP Header 对请求进行过滤。

这可以与反向代理一起使用,如负载均衡器或web应用防火墙,只有当请求来自这些反向代理所使用的受信任的IP地址列表时,才应该被允许。

下面的例子配置了一个 XForwardedRemoteAddr 路由谓词。

Example 13. application.yml

spring:

cloud:

gateway:

routes:

- id: xforwarded_remoteaddr_route

uri: https://example.org

predicates:

- XForwardedRemoteAddr=192.168.1.1/24

例如,如果 X-Forwarded-For Header 包含 192.168.1.10,则该路由匹配。

6. GatewayFilter 工厂

路由(Route)过滤器(Filter)允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是一个特定的路由。Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。

关于如何使用以下任何过滤器的更详细的例子,请看 单元测试。

6.1. AddRequestHeader

AddRequestHeader GatewayFilter 工厂需要一个 name 和 value 参数。下面的例子配置了一个 AddRequestHeader GatewayFilter。

Example 14. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

filters:

- AddRequestHeader=X-Request-red, blue

这个列表将 X-Request-red:blue header添加到所有匹配请求的下游请求的header信息中。

AddRequestHeader 知道用于匹配路径或主机的URI变量。URI变量可以在值中使用,并在运行时被扩展。下面的例子配置了一个 AddRequestHeader GatewayFilter,它使用一个变量。

Example 15. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- AddRequestHeader=X-Request-Red, Blue-{segment}

6.2. AddRequestHeadersIfNotPresent

AddRequestHeadersIfNotPresent GatewayFilter 工厂接受一个由冒号分隔的 name 和 value 键值对的集合。下面的例子配置了一个 AddRequestHeadersIfNotPresent GatewayFilter。

Example 16. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_headers_route

uri: https://example.org

filters:

- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green

这个列表为所有匹配的请求在下游请求的header信息中添加了两个header信息 X-Request-Color-1:blue 和 X-Request-Color-2:green。这类似于 AddRequestHeader 的工作方式,但与 AddRequestHeader 不同的是,它只在header 信息不存在的情况下才会这样做。否则,客户端请求中的原始值将被发送。

此外,要设置一个多值header,可以多次使用header的名称,如 AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-1:green。

AddRequestHeadersIfNotPresent 也支持URI变量,用于匹配路径或主机。URI变量可以在值中使用,并在运行时被扩展。下面的例子配置了一个使用变量的 AddRequestHeadersIfNotPresent GatewayFilter。

Example 17. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- AddRequestHeadersIfNotPresent=X-Request-Red:Blue-{segment}

6.3. AddRequestParameter

AddRequestParameter GatewayFilter Factory需要一个 name 和 value 参数。下面的例子配置了一个 AddRequestParameter GatewayFilter。

Example 18. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_parameter_route

uri: https://example.org

filters:

- AddRequestParameter=red, blue

这将为所有匹配的请求在下游请求的查询字符串中添加 red=blue。

AddRequestParameter 知道用于匹配路径或主机的URI变量。URI变量可以在值中使用,并在运行时被扩展。下面的例子配置了一个 AddRequestParameter GatewayFilter,它使用了一个变量。

Example 19. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_parameter_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- AddRequestParameter=foo, bar-{segment}

6.4. AddResponseHeader

AddResponseHeader GatewayFilter 工厂需要一个 name 和 value 参数。下面的例子配置了一个 AddResponseHeader GatewayFilter。

Example 20. application.yml

spring:

cloud:

gateway:

routes:

- id: add_response_header_route

uri: https://example.org

filters:

- AddResponseHeader=X-Response-Red, Blue

这将把 X-Response-Red:Blue header添加到所有匹配请求的下游响应的header中。

AddResponseHeader 知道用于匹配路径或主机的URI变量。URI变量可以在值中使用,并在运行时被扩展。下面的例子配置了一个 AddResponseHeader GatewayFilter,它使用了一个变量。

Example 21. application.yml

spring:

cloud:

gateway:

routes:

- id: add_response_header_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- AddResponseHeader=foo, bar-{segment}

6.5. CircuitBreaker

Spring Cloud CircuitBreaker GatewayFilter 工厂使用Spring Cloud CircuitBreaker API 将 Gateway 路由包裹在一个熔断器中。Spring Cloud CircuitBreaker 支持多个可与 Spring Cloud Gateway 一起使用的库。Spring Cloud 支持 Resilience4J 开箱即用。

要启用 Spring Cloud CircuitBreaker 过滤器,你需要添加 spring-cloud-starter-circuitbreaker-reactor-resilience4j 依赖。下面的例子配置了一个 Spring Cloud CircuitBreaker GatewayFilter。

Example 22. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: https://example.org

filters:

- CircuitBreaker=myCircuitBreaker

要配置熔断器,请参阅你所使用的底层熔断器实现的配置。

Resilience4J 文档

Spring Cloud CircuitBreaker 过滤器还可以接受一个可选的 fallbackUri 参数。目前,只支持 forward: 模式的URI。如果fallback被调用,请求将被转发到URI所匹配的控制器。下面的例子配置了这样一个fallback。

Example 23. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis

- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

也可以通过Java来实现相同的配置,如下。

Example 24. Application.java

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")

.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))

.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")

.build();

}

当熔断器 fallback 被调用时,这个例子转发到 /inCaseofFailureUseThis URI。请注意,这个例子还演示了(可选)Spring Cloud LoadBalancer 的负载均衡(由目标URI上的 lb 前缀定义)。

CircuitBreaker 还支持 fallbackUri 中的URI变量。这允许更复杂的路由选项,比如使用 PathPattern 表达式 转发原始主机或URL路径的部分。

在下面的例子中,调用 consumingServiceEndpoint/users/1 将被重定向到 inCaseOfFailureUseThis/users/1。

Example 25. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint/{*segments}

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis/{segments}

一般情况下是使用 fallbackUri 来定义网关应用程序中的内部controller或handler。然而,你也可以将请求重新路由到外部应用程序的controller或handler,如下所示。

Example 26. application.yml

spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: CircuitBreaker

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback

在这个例子中,网关应用程序中没有 fallback 端点或处理程序。然而,在另一个应用程序中有一个,在 localhost:9994 下注册。

在请求被转发到 fallback 的情况下,Spring Cloud CircuitBreaker Gateway 过滤器也提供了造成这种情况的 Throwable。它作为 ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性被添加到 ServerWebExchange 中,在网关应用中处理 fallback 时可以使用。

对于外部 controller/handler 的情况,可以添加带有异常细节的header。你可以在FallbackHeaders GatewayFilter Factory 部分找到更多关于这样做的信息。

6.5.1. 熔断指定的状态码

在某些情况下,你可能想根据它所包裹的路由返回的状态码来熔断。断路器配置对象需要一个状态码列表,如果返回这些代码将导致断路器熔断。当设置你想让断路器熔断的状态代码时,你可以使用一个带有状态码值的 int 或 HttpStatus 枚举的字符串表示。

Example 27. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis

statusCodes:

- 500

- "NOT_FOUND"

Example 28. Application.java

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")

.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))

.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")

.build();

}

6.6. CacheRequestBody

有些情况下,有必要读取请求体。由于请求体只能被读取一次,我们需要缓存请求体。你可以使用 CacheRequestBody 过滤器来缓存请求体,然后再把它发送到下游,从 exchange 属性中获取请求体。

下面显示了如何缓存请求体 GatewayFilter:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("cache_request_body_route", r -> r.path("/downstream/**")

.filters(f -> f.prefixPath("/httpbin")

.cacheRequestBody(String.class).uri(uri))

.build();

}

Example 29. application.yml

spring:

cloud:

gateway:

routes:

- id: cache_request_body_route

uri: lb://downstream

predicates:

- Path=/downstream/**

filters:

- name: CacheRequestBody

args:

bodyClass: java.lang.String

CacheRequestBody 提取请求体并将其转换为一个 body 类(比如前面例子中定义的 java.lang.String)。然后,CacheRequestBody 把它放在 ServerWebExchange.getAttributes() 提供的属性中,其KEY值在 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 中定义。

这个过滤器只对HTTP(包括HTTPS)请求起作用。

6.7. DedupeResponseHeader

DedupeResponseHeader GatewayFilter 工厂接受一个 name 参数和一个可选的 strategy 参数。name 可以包含一个以空格分隔的header名称列表。下面的例子配置了一个 DedupeResponseHeader GatewayFilter。

Example 30. application.yml

spring:

cloud:

gateway:

routes:

- id: dedupe_response_header_route

uri: https://example.org

filters:

- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

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

DedupeResponseHeader 过滤器还接受一个可选的 strategy 参数。接受的值是 RETAIN_FIRST(默认)、RETAIN_LAST 和 RETAIN_UNIQUE。

6.8. FallbackHeaders

通过 FallbackHeaders 工厂,你可以在转发到外部应用程序中的 fallbackUri 的请求的header中添加Spring Cloud CircuitBreaker的执行异常细节,如以下场景。

Example 31. application.yml

spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: CircuitBreaker

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback

filters:

- name: FallbackHeaders

args:

executionExceptionTypeHeaderName: Test-Header

在这个例子中,在运行断路器时发生执行异常后,请求被转发到运行在 localhost:9994 的应用程序中的 fallback 端点或 handler。带有异常类型、消息和(如果有)根本原因的异常类型和消息的 header 被 FallbackHeaders 过滤器添加到该请求中。

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

executionExceptionTypeHeaderName ("Execution-Exception-Type")

executionExceptionMessageHeaderName ("Execution-Exception-Message")

rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

关于断路器和网关的更多信息,请参见 Spring Cloud CircuitBreaker Factory 部分 。

6.9. JsonToGrpc

JSONToGRPCFilter GatewayFilter Factory 将一个JSON payload 转换为gRPC请求。

该过滤器需要以下参数。

protoDescriptor: Proto描述文件。

这个文件可以用 protoc 生成,并指定 --descriptor_set_out 标志。

protoc --proto_path=src/main/resources/proto/ \

--descriptor_set_out=src/main/resources/proto/hello.pb \

src/main/resources/proto/hello.proto

protoFile: Proto定义文件。

service: 处理请求的服务的全名称。

method: 处理该请求的服务中的方法名称。

支持 streaming。

application.yml.

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("json-grpc", r -> r.path("/json/hello").filters(f -> {

String protoDescriptor = "file:src/main/proto/hello.pb";

String protoFile = "file:src/main/proto/hello.proto";

String service = "HelloService";

String method = "hello";

return f.jsonToGRPC(protoDescriptor, protoFile, service, method);

}).uri(uri))

spring:

cloud:

gateway:

routes:

- id: json-grpc

uri: https://localhost:6565/testhello

predicates:

- Path=/json/**

filters:

- name: JsonToGrpc

args:

protoDescriptor: file:proto/hello.pb

protoFile: file:proto/hello.proto

service: com.example.grpcserver.hello.HelloService

method: hello

当通过网关向 /json/hello 发出请求时,该请求通过使用 hello.proto 中提供的定义进行转换,发送到 com.example.grpcserver.hello.HelloService/hello,返回的响应被转换为JSON。

默认情况下,它通过使用默认的 TrustManagerFactory 创建一个 NettyChannel。然而,你可以通过创建一个 GrpcSslConfigurer 类型的bean来定制这个 TrustManager。

@Configuration

public class GRPCLocalConfiguration {

@Bean

public GRPCSSLContext sslContext() {

TrustManager trustManager = trustAllCerts();

return new GRPCSSLContext(trustManager);

}

}

6.10. LocalResponseCache

这个过滤器允许缓存响应体和header,遵循以下规则。

它只能缓存无请求体的GET请求。

它只对以下状态代码之一的响应进行缓存。HTTP 200(OK),HTTP 206(部分内容),或HTTP 301(永久移动)。

如果 Cache-Control header不允许,响应数据就不会被缓存(请求中存在 no-store 或响应中存在 no-store 或 private)。

如果响应已经被缓存,并且在 Cache-Control 头中用 no-cache 值执行一个新的请求,它将返回一个304(未修改)的无body的响应。

这个过滤器(配置每个路由的本地响应缓存)只有在启用了本地响应全局缓存的情况下才可用。

它接受第一个参数,用于覆盖缓存条目过期的时间(用 s 表示秒,用 m 表示分钟,用 h 表示小时),第二个参数用于设置该路由驱逐条目的最大缓存大小(KB、MB或GB)。

下面的列表显示了如何添加本地响应缓存 GatewayFilter。

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")

.filters(f -> f.prefixPath("/httpbin")

.localResponseCache(Duration.ofMinutes(30), "500MB")

).uri(uri))

.build();

}

或者,这样:

application.yaml

spring:

cloud:

gateway:

routes:

- id: resource

uri: http://localhost:9000

predicates:

- Path=/resource

filters:

- LocalResponseCache=30m,500MB

这个过滤器还自动计算 HTTP Cache-Control header中的 max-age 值。只有在原始响应中存在 max-age 的情况下,才会用 timeToLive 配置参数中设置的秒数重写该值。在连续的调用中,这个值会以响应过期前的剩余秒数重新计算。

6.11. MapRequestHeader

MapRequestHeader GatewayFilter 工厂接受 fromHeader 和 toHeader 参数。它创建一个新的命名header(toHeader),并从传入的http请求的现有命名头(fromHeader)中提取值。如果输入的header不存在,过滤器没有任何影响。如果新的命名header信息已经存在,它的值就会被增加新的值。下面的例子配置了一个 MapRequestHeader。

Example 32. application.yml

spring:

cloud:

gateway:

routes:

- id: map_request_header_route

uri: https://example.org

filters:

- MapRequestHeader=Blue, X-Request-Red

这将在下游请求中添加 X-Request-Red: 头,并从传入的HTTP请求的 Blue 头中更新数值。

6.12. ModifyRequestBody

你可以使用 ModifyRequestBody 过滤器,在网关向下游发送请求体之前对其进行修改。

这个过滤器只能通过使用Java DSL来配置。

下面显示了如何使用 GatewayFilter 修改请求体:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,

(exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))

.build();

}

static class Hello {

String message;

public Hello() { }

public Hello(String message) {

this.message = message;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

如果请求没有正文,RewriteFilter 将被传递为 null。应该返回 Mono.empty() 来指定请求中缺少的主体。

6.13. ModifyResponseBody

你可以使用 ModifyResponseBody 过滤器来修改响应体,然后再把它送回给客户端。

这个过滤器只能通过使用Java DSL来配置。

下面显示了如何使用 GatewayFilter 修改响应体 。

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyResponseBody(String.class, String.class,

(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))

.build();

}

如果响应没有正文,RewriteFilter 将被传递为 null。应该返回 Mono.empty() 来指定响应中缺少的主体。

6.14. PrefixPath

PrefixPath GatewayFilter 工厂需要一个 prefix 参数。下面的例子配置了一个 PrefixPath GatewayFilter。

Example 33. application.yml

spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: https://example.org

filters:

- PrefixPath=/mypath

这就把 /mypath 作为所有匹配请求的路径的前缀。因此,一个到 /hello 的请求会被发送到 /mypath/hello。

6.15. PreserveHostHeader

PreserveHostHeader GatewayFilter 工厂没有参数。这个过滤器设置一个请求属性(request attribute),路由过滤器(routing filter)会检查该属性,以确定是否应该发送原始的主机头,而不是由HTTP客户端确定的主机头。下面的例子配置了一个 PreserveHostHeader GatewayFilter。

Example 34. application.yml

spring:

cloud:

gateway:

routes:

- id: preserve_host_route

uri: https://example.org

filters:

- PreserveHostHeader

6.16. RedirectTo

RedirectTo GatewayFilter 工厂需要两个参数,status 和 url。status 参数应该是一个300系列的重定向 HTTP 状态码,如301。url 参数应该是一个有效的URL。这就是 Location header 的值。对于相对重定向,你应该使用 uri: no://op 作为路由定义的uri。下面的列表配置了一个 RedirectTo GatewayFilter。

Example 35. application.yml

spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: https://example.org

filters:

- RedirectTo=302, https://acme.org

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

6.17. RemoveJsonAttributesResponseBody

RemoveJsonAttributesResponseBody GatewayFilter 工厂接收了一个要搜索的属性名称(attribute name)集合,列表中的最后一个参数可以是一个布尔值,用来删除根级的属性(如果该参数未定义,那就是默认值 false)或递归(true)。它提供了一个方便的方法,通过删除属性来应用于JSON body内容的转换。

下面的例子配置了一个 RemoveJsonAttributesResponseBody GatewayFilter。

Example 36. application.yml

spring:

cloud:

gateway:

routes:

- id: removejsonattributes_route

uri: https://example.org

filters:

- RemoveJsonAttributesResponseBody=id,color

这从根层的JSON body中删除了属性 "id" 和 "color"。

下面的例子配置了一个 RemoveJsonAttributesResponseBody GatewayFilter,它使用了可选的最后参数。

Example 37. application.yml

spring:

cloud:

gateway:

routes:

- id: removejsonattributes_recursively_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- RemoveJsonAttributesResponseBody=id,color,true

这将从任何级别的JSON body中移除属性 "id" 和 "color"。

6.18. RemoveRequestHeader

RemoveRequestHeader GatewayFilter 工厂需要一个 name 参数。它是要被删除的header的名称。下面配置了一个 RemoveRequestHeader GatewayFilter。

Example 38. application.yml

spring:

cloud:

gateway:

routes:

- id: removerequestheader_route

uri: https://example.org

filters:

- RemoveRequestHeader=X-Request-Foo

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

6.19. RemoveRequestParameter

RemoveRequestParameter GatewayFilter 工厂需要一个 name 参数。它是要删除的查询参数的名称。下面的例子配置了一个 RemoveRequestParameter GatewayFilter。

Example 39. application.yml

spring:

cloud:

gateway:

routes:

- id: removerequestparameter_route

uri: https://example.org

filters:

- RemoveRequestParameter=red

这将在向下游发送之前删除 red 参数。

6.20. RemoveResponseHeader

RemoveResponseHeader GatewayFilter 工厂需要一个 name 参数。它是要被移除的 header 的名称。下面的列表配置了一个 RemoveResponseHeader GatewayFilter。

Example 40. application.yml

spring:

cloud:

gateway:

routes:

- id: removeresponseheader_route

uri: https://example.org

filters:

- RemoveResponseHeader=X-Response-Foo

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

要删除任何类型的敏感标头,你应该为任何你可能想这样做的路由配置这个过滤器。此外,你可以通过使用 spring.cloud.gateway.default-filters 配置一次此过滤器,并将其应用于所有路由。

6.21. RequestHeaderSize

RequestHeaderSize GatewayFilter 工厂接受 maxSize 和 errorHeaderName 参数。maxSize 参数是请求头(包括key和value)所允许的最大数据大小。errorHeaderName 参数设置包含错误信息的响应头的名称,默认为 "errorMessage"。下面的列表配置了一个 RequestHeaderSize GatewayFilter。

Example 41. application.yml

spring:

cloud:

gateway:

routes:

- id: requestheadersize_route

uri: https://example.org

filters:

- RequestHeaderSize=1000B

如果任何请求头的大小超过1000字节,这将发送一个 431状态码的响应。

6.22. RequestRateLimiter

RequestRateLimiter GatewayFilter 工厂使用 RateLimiter 实现来确定是否允许当前请求继续进行。如果不允许,就会返回 HTTP 429 - Too Many Requests(默认)的状态。

这个过滤器需要一个可选的 keyResolver 参数和特定于速率限制器的参数(在本节后面描述)。

keyResolver 是一个实现了 KeyResolver 接口的Bean。在配置中,使用SpEL来引用Bean的名字。#{@myKeyResolver} 是一个SpEL表达式,它引用了一个名为 myKeyResolver 的bean。下面的列表显示了 KeyResolver 的接口。

Example 42. KeyResolver.java

public interface KeyResolver {

Mono resolve(ServerWebExchange exchange);

}

KeyResolver 接口让可插拔的策略导出限制请求的key。在未来的里程碑版本中,会有一些 KeyResolver 的实现。

KeyResolver 的默认实现是 PrincipalNameKeyResolver,它从 ServerWebExchange 中检索 Principal 并调用 Principal.getName()。

默认情况下,如果 KeyResolver 没有找到一个 key,请求会被拒绝。你可以通过设置 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true 或 false)和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 属性来调整这种行为。

RequestRateLimiter 不能用 "快捷方式" 来配置。下面的例子是无效的。

Example 43. application.properties

# 无效的快捷方式配置

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

6.22.1. Redis RateLimiter

Redis的实现是基于 Stripe 的工作。它需要使用 spring-boot-starter-data-redis-reactive Spring Boot Starter。

使用的算法是 令牌桶算法。

redis-rate-limiter.replenishRate 属性定义了每秒钟允许多少个请求(不算放弃的请求)。这是令牌桶被填充的速度。

redis-rate-limiter.burstCapacity 属性是一个用户在一秒钟内允许的最大请求数(不算放弃的请求)。这是令牌桶可以容纳的令牌数量。将此值设置为零会阻止所有请求。

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

一个稳定的速率是通过在 replenishRate 和 burstCapacity 中设置相同的值来实现的。可以通过设置高于补给率的 burstCapacity 来允许临时的突发。在这种情况下,速率限制器需要在突发之间允许一些时间(根据 replenishRate),因为连续两次突发会导致请求被放弃(HTTP 429 - Too Many Requests)。下面的列表配置了一个 redis-rate-limiter。

低于 1个请求/s 的速率限制是通过将 replenishRate 设置为想要的请求数, requestTokens 设置为秒数,burstCapacity 设置为 replenishRate 和 requestTokens 的乘积来完成的。例如,设置 replenishRate=1,requestedTokens=60,burstCapacity=60,结果是1个请求/分钟的限制。

Example 44. application.yml

spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: https://example.org

filters:

- name: RequestRateLimiter

args:

redis-rate-limiter.replenishRate: 10

redis-rate-limiter.burstCapacity: 20

redis-rate-limiter.requestedTokens: 1

下面的例子在Java中配置了一个 KeyResolver。

Example 45. Config.java

@Bean

KeyResolver userKeyResolver() {

return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));

}

这定义了每个用户的请求率限制为10。爆发20次是允许的,但是,在下一秒,只有10个请求可用。KeyResolver 是一个简单的,获得 user 请求参数。

不建议在生产中使用这个方法

你也可以把速率限制器定义为一个实现 RateLimiter 接口的bean。在配置中,你可以用SpEL来引用bean的名字。#{@myRateLimiter} 是一个SpEL表达式,它引用了一个名为 myRateLimiter 的 bean。下面的清单定义了一个速率限制器,它使用了前面清单中定义的 KeyResolver。

Example 46. application.yml

spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: https://example.org

filters:

- name: RequestRateLimiter

args:

rate-limiter: "#{@myRateLimiter}"

key-resolver: "#{@userKeyResolver}"

6.23. RewriteLocationResponseHeader

RewriteLocationResponseHeader GatewayFilter 工厂修改 Location 响应头的值,通常是为了去掉后台的特定细节。它需要 stripVersionMode、locationHeaderName、hostValue 和 protocolsRegex 参数。下面的清单配置了一个 RewriteLocationResponseHeader GatewayFilter。

Example 47. application.yml

spring:

cloud:

gateway:

routes:

- id: rewritelocationresponseheader_route

uri: http://example.org

filters:

- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

例如,对于一个 POST api.example.com/some/object/name 的请求, Location 响应头值 object-service.prod.example.net/v2/some/object/id 被改写为 api.example.com/some/object/id。

stripVersionMode 参数有以下可能的值。NEVER_STRIP、AS_IN_REQUEST(默认)和 ALWAYS_STRIP。

NEVER_STRIP: 即使最初的请求路径不包含version,version也不会被剥离。

AS_IN_REQUEST: 只有当原始请求路径不包含version时,才会剥离version。

ALWAYS_STRIP: version 总是被剥离,即使原始请求路径包含version 。

hostValue 参数,如果提供的话,将用于替换响应的 Location 头的 host:port 部分。如果没有提供,则使用 Host 请求头的值。

protocolsRegex 参数必须是一个有效的 regex String,协议名称将与之匹配。如果没有匹配,过滤器不做任何事情。默认是 http|https|ftp|ftps。

6.24. RewritePath

RewritePath GatewayFilter 工厂接收一个路径 regexp 参数和一个 replacement 参数。这是用Java正则表达式来重写请求路径的一种灵活方式。下面的列表配置了一个 RewritePath GatewayFilter。

Example 48. application.yml

spring:

cloud:

gateway:

routes:

- id: rewritepath_route

uri: https://example.org

predicates:

- Path=/red/**

filters:

- RewritePath=/red/?(?.*), /$\{segment}

对于请求路径为 /red/blue 的情况,在进行下游请求之前将路径设置为 /blue。注意,由于YAML的规范,$ 应该被替换成 $\。

6.25. RewriteResponseHeader

RewriteResponseHeader GatewayFilter 工厂接受 name、regexp 和 replacement 参数。它使用Java正则表达式,以一种灵活的方式重写响应头的值。下面的例子配置了一个 RewriteResponseHeader GatewayFilter。

Example 49. application.yml

spring:

cloud:

gateway:

routes:

- id: rewriteresponseheader_route

uri: https://example.org

filters:

- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

对于一个 /42?user=ford&password=omg!what&flag=true 的header值,在发出下游请求后,它被设置为 /42?user=ford&password=***&flag=true。因为YAML规范,你必须用 $\ 来表示 $。

6.26. SaveSession

SaveSession GatewayFilter 工厂在转发下游调用之前强制进行 WebSession::save 操作。这在使用类似 Spring Session 的懒数据存储时特别有用,因为你需要确保在进行转发调用之前已经保存了Session状态。下面的例子配置了一个 SaveSession GatewayFilter。

Example 50. application.yml

spring:

cloud:

gateway:

routes:

- id: save_session

uri: https://example.org

predicates:

- Path=/foo/**

filters:

- SaveSession

如果你将 Spring Security 与 Spring Session 集成,并希望确保安全细节(security detail)已被转发到远程进程,这一点至关重要。

6.27. SecureHeaders

根据 这篇博客的建议,SecureHeaders GatewayFilter 工厂在响应中添加了一些头信息。

以下header信息(显示为其默认值)被添加。

X-Xss-Protection:1 (mode=block)

Strict-Transport-Security (max-age=631138519)

X-Frame-Options (DENY)

X-Content-Type-Options (nosniff)

Referrer-Policy (no-referrer)

Content-Security-Policy (default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline)'

X-Download-Options (noopen)

X-Permitted-Cross-Domain-Policies (none)

要改变默认值,请在 spring.cloud.gateway.filter.secure-headers 命名空间中设置相应的属性。以下是可用的属性。

xss-protection-header

strict-transport-security

frame-options

content-type-options

referrer-policy

content-security-policy

download-options

permitted-cross-domain-policies

要禁用默认值,请用逗号分隔的值设置 spring.cloud.gateway.filter.secure-headers.disable 属性,如下。

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

需要使用 secure header 的小写全名来禁用它。

6.28. SetPath

SetPath GatewayFilter 工厂接受一个路径模板参数。它提供了一种简单的方法,通过允许模板化的路径段来操作请求路径。这使用了 Spring Framework 的URI模板。允许多个匹配段。下面的例子配置了一个 SetPath GatewayFilter。

Example 51. application.yml

spring:

cloud:

gateway:

routes:

- id: setpath_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- SetPath=/{segment}

对于请求路径为 /red/blue 的情况,在进行下行请求之前,将路径设置为 /blue。

6.29. SetRequestHeader

SetRequestHeader GatewayFilter 工厂接受 name 和 value 参数。下面的列表配置了一个 SetRequestHeader GatewayFilter。

Example 52. application.yml

spring:

cloud:

gateway:

routes:

- id: setrequestheader_route

uri: https://example.org

filters:

- SetRequestHeader=X-Request-Red, Blue

这 GatewayFilter 会替换(而不是添加)所有给定名称的 header 信息。

因此,如果下游服务器以 X-Request-Red:1234 响应,它将被替换为 X-Request-Red:Blue,这就是下游服务会收到的。

SetRequestHeader 知道用于匹配路径或主机的URI变量。URI变量可以在值中使用,并在运行时被扩展。下面的例子配置了一个 SetRequestHeader GatewayFilter,它使用了一个变量。

Example 53. application.yml

spring:

cloud:

gateway:

routes:

- id: setrequestheader_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- SetRequestHeader=foo, bar-{segment}

6.30. SetResponseHeader

SetResponseHeader GatewayFilter 工厂接受 name 和 value 参数。下面的列表配置了一个 SetResponseHeader GatewayFilter。

Example 54. application.yml

spring:

cloud:

gateway:

routes:

- id: setresponseheader_route

uri: https://example.org

filters:

- SetResponseHeader=X-Response-Red, Blue

这个 GatewayFilter 会替换(而不是添加)所有带有给定名称的头信息。

因此,如果下游服务器以 X-Response-Red:1234 响应,它将被替换为 X-Response-Red:Blue,这就是网关客户端将收到的内容。

SetResponseHeader 知道用于匹配路径或主机的URI变量。URI变量可以在值中使用,并将在运行时被扩展。下面的例子配置了一个 SetResponseHeader GatewayFilter,它使用了一个变量。

Example 55. application.yml

spring:

cloud:

gateway:

routes:

- id: setresponseheader_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- SetResponseHeader=foo, bar-{segment}

6.31. SetStatus

SetStatus GatewayFilter 工厂只接受一个参数,即 status。它必须是一个有效的Spring HttpStatus。它可以是 404 的int值或枚举的字符串表示: NOT_FOUND。下面的列表配置了一个 SetStatus GatewayFilter。

Example 56. application.yml

spring:

cloud:

gateway:

routes:

- id: setstatusstring_route

uri: https://example.org

filters:

- SetStatus=UNAUTHORIZED

- id: setstatusint_route

uri: https://example.org

filters:

- SetStatus=401

在这两种情况下,响应的HTTP状态被设置为401。

你可以配置 SetStatus GatewayFilter,使其在响应中的头中返回代理请求的原始HTTP状态代码。如果配置了以下属性,该头会被添加到响应中。

Example 57. application.yml

spring:

cloud:

gateway:

set-status:

original-status-header-name: original-http-status

6.32. StripPrefix

StripPrefix GatewayFilter 工厂需要一个参数,即 parts。parts 参数表示在向下游发送请求之前要从路径中剥离的部分的数量。下面的列表配置了一个 StripPrefix GatewayFilter。

Example 58. application.yml

spring:

cloud:

gateway:

routes:

- id: nameRoot

uri: https://nameservice

predicates:

- Path=/name/**

filters:

- StripPrefix=2

当通过网关向 /name/blue/red 发出请求时,向 nameservice 发出的请求看起来像 nameservice/red。

6.33. Retry

Retry GatewayFilter 工厂支持以下参数。

retries: 应该尝试的重试次数。

statuses: 应该重试的HTTP状态代码,用 org.springframework.http.HttpStatus 表示。

methods: 应该重试的HTTP方法,用 org.springframework.http.HttpMethod 来表示。

series: 要重试的状态代码系列,用 org.springframework.http.HttpStatus.Series 表示。

exceptions: 抛出的异常的列表,应该重试。

backoff: 为重试配置的指数式backoff。重试是在 backoff 间隔 firstBackoff * (factor ^ n) 之后进行的,其中 n 是迭代次数。如果配置了 maxBackoff,应用的最大 backoff 时间被限制在 maxBackoff。如果 basedOnPreviousValue 为 true,则通过使用 prevBackoff * factor 来计算backoff。

如果启用,为 Retry filter 配置的默认值如下。

retries: 三次

series: 5XX系列

methods: GET 请求

exceptions: IOException 和 TimeoutException

backoff: disabled

下面配置了一个 Retry GatewayFilter。

Example 59. application.yml

spring:

cloud:

gateway:

routes:

- id: retry_test

uri: http://localhost:8080/flakey

predicates:

- Host=*.retry.com

filters:

- name: Retry

args:

retries: 3

statuses: BAD_GATEWAY

methods: GET,POST

backoff:

firstBackoff: 10ms

maxBackoff: 50ms

factor: 2

basedOnPreviousValue: false

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

当对任何带有body的HTTP方法使用 retry filter 时,body将被缓存,网关将变得内存受限。body被缓存在 ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR 定义的请求属性(request attribute)中。该对象的类型是 org.springframework.core.io.buffer.DataBuffer。

一个简化的 "快捷" 方式可以用一个 status 和 method 来添加。

以下两个例子是等同的。

Example 60. application.yml

spring:

cloud:

gateway:

routes:

- id: retry_route

uri: https://example.org

filters:

- name: Retry

args:

retries: 3

statuses: INTERNAL_SERVER_ERROR

methods: GET

backoff:

firstBackoff: 10ms

maxBackoff: 50ms

factor: 2

basedOnPreviousValue: false

- id: retryshortcut_route

uri: https://example.org

filters:

- Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false

6.34. RequestSize

当请求的大小超过允许的限制时,RequestSize GatewayFilter 工厂可以限制请求到达下游服务。该过滤器需要一个 maxSize 参数。maxSize 是一个 DataSize 类型,所以值可以定义为一个数字,后面有一个可选的 DataUnit 后缀,如 'KB' 或’MB'。默认是 'B',表示字节。它是以字节为单位定义的请求的可允许的大小限制。下面的列表配置了一个 RequestSize GatewayFilter。

Example 61. application.yml

spring:

cloud:

gateway:

routes:

- id: request_size_route

uri: http://localhost:8080/upload

predicates:

- Path=/upload

filters:

- name: RequestSize

args:

maxSize: 5000000

RequestSize GatewayFilter 工厂将响应状态设置为 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

如果在路由定义中没有提供filter参数,默认请求大小被设置为5MB。

6.35. SetRequestHostHeader

在某些情况下,host 头可能需要被重写。在这种情况下,SetRequestHostHeader GatewayFilter 工厂可以将现有的 host header 替换成指定的值。该过滤器需要一个 host 参数。下面的列表配置了一个 SetRequestHostHeader GatewayFilter。

Example 62. application.yml

spring:

cloud:

gateway:

routes:

- id: set_request_host_header_route

uri: http://localhost:8080/headers

predicates:

- Path=/headers

filters:

- name: SetRequestHostHeader

args:

host: example.org

SetRequestHostHeader GatewayFilter 工厂将 host 头的值替换为 example.org。

6.36. TokenRelay

Token Relay是指OAuth2消费者作为客户端,将传入的令牌转发给传出的资源请求。消费者可以是一个纯粹的客户端(如SSO应用程序)或一个资源服务器。

Spring Cloud Gateway 可以将 OAuth2 访问令牌转发到它所代理的服务的下游。为了在网关中添加这一功能,你需要像这样添加 TokenRelayGatewayFilterFactory。

App.java

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

return builder.routes()

.route("resource", r -> r.path("/resource")

.filters(f -> f.tokenRelay())

.uri("http://localhost:9000"))

.build();

}

或者,这样。

application.yaml

spring:

cloud:

gateway:

routes:

- id: resource

uri: http://localhost:9000

predicates:

- Path=/resource

filters:

- TokenRelay=

它将(除了登录用户和抓取令牌之外)把认证令牌传递给下游的服务(在这里是 /resource)。

要为 Spring Cloud Gateway 启用这个功能,需要添加以下依赖

org.springframework.boot:spring-boot-starter-oauth2-client

它是如何工作的? {githubmaster}/src/main/java/org/springframework/cloud/gateway/security/TokenRelayGatewayFilterFactory.java[filter]从当前认证的用户中提取一个访问令牌,并将其放在下游请求的请求头中。

完整的工作样本见 该项目。

只有当适当的 spring.security.oauth2.client.* 属性被设置时, TokenRelayGatewayFilterFactory Bean才会被创建,这将触发 ReactiveClientRegistrationRepository Bean的创建。

TokenRelayGatewayFilterFactory 使用的 ReactiveOAuth2AuthorizedClientService 的默认实现使用了一个内存数据存储。如果你需要一个更强大的解决方案,你将需要提供你自己的实现 ReactiveOAuth2AuthorizedClientService。

6.37. 默认 Filter

要添加一个filter并将其应用于所有路由,可以使用 spring.cloud.gateway.default-filters。这个属性需要一个filter的列表。下面的列表定义了一组默认filter。

Example 63. application.yml

spring:

cloud:

gateway:

default-filters:

- AddResponseHeader=X-Response-Default-Red, Default-Blue

- PrefixPath=/httpbin

7. 全局 Filter

GlobalFilter 接口的签名与 GatewayFilter 相同。这些是特殊的过滤器,有条件地应用于所有路由。

这个接口和它的用法在未来的里程碑版本中可能会有变化。

7.1. GlobalFilter 组合和 GatewayFilter 的顺序

当一个请求与路由匹配时,filter web handler将 GlobalFilter 的所有实例和 GatewayFilter 的所有路由特定实例添加到一个过滤链中。这个组合的过滤链由 org.springframework.core.Ordered 接口进行排序,你可以通过实现 getOrder() 方法来设置这个接口。

由于 Spring Cloud Gateway 区分了过滤器逻辑执行的 “pre” 和 “post” 阶段(见如何工作),优先级最高的过滤器在 “pre” 阶段是第一个,在 “post” 阶段是最后一个。

下面的列表配置了一个过滤器链。

Example 64. ExampleConfiguration.java

@Bean

public GlobalFilter customFilter() {

return new CustomGlobalFilter();

}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

log.info("custom global filter");

return chain.filter(exchange);

}

@Override

public int getOrder() {

return -1;

}

}

7.2. Gateway Metrics(指标) Filter

要启用网关指标,请添加 spring-boot-starter-actuator 作为项目依赖。然后,默认情况下,只要 spring.cloud.gateway.metrics.enabled 属性没有被设置为 false,网关指标过滤器就会运行。这个过滤器添加了一个名为 spring.cloud.gateway.requests 的定时器指标,标签如下。

routeId: 路由(route) ID.

routeUri: API被路由到的URI。

outcome: 结果,由 HttpStatus.Series 分类。

status: 返回给客户端的请求的HTTP状态。

httpStatusCode: 返回给客户端的请求的HTTP状态。

httpMethod: 请求使用的HTTP方法。

此外,通过 spring.cloud.gateway.metrics.tags.path.enabled 属性(默认为 false),你可以用路径标签(path tag)激活一个额外的指标。

path: 请求的路径。

这些指标可以从 /actuator/metrics/spring.cloud.gateway.requests 中抓取,并可以很容易地与 Prometheus 集成,创建一个 Grafana dashboard。

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

7.3. Local Response Cache Filter

如果 LocalResponseCache 的相关属性被启用(spring.cloud.gateway.filter.local-response-cache.enabled),它就会运行,并为所有符合以下条件的响应激活一个本地缓存。

请求是一个无body的 GET。

响应具有以下状态代码之一。HTTP 200 (OK), HTTP 206 (Partial Content), 或 HTTP 301 (Moved Permanently)。

HTTP Cache-Control 头允许缓存(这意味着它没有以下任何值。在请求中出现 no-store,在响应中出现 no-store 或 private)。

它接受两个配置参数:

spring.cloud.gateway.filter.local-response-cache.size。设置该路由驱逐条目的最大缓存大小(单位:KB、MB 和 GB)。

spring.cloud.gateway.filter.local-response-cache.timeToLive。设置缓存条目过期的时间(用 s 表示秒、m 表示分钟、h 表示小时)。如果没有配置这些参数,但启用了全局过滤器,默认情况下,它为缓存的响应配置了5分钟的生存时间。

这个 filter 还实现了自动计算 HTTP Cache-Control 头中的 max-age 值。如果原始响应中存在 max-age,则该值会以 timeToLive 配置参数中设置的秒数重写。在随后的调用中,这个值会以响应过期前的剩余秒数重新计算。

如果你的项目创建了自定义的 CacheManager Bean,它需要用 @Primary 来标记,或者用 @Qualifier 来注入。

7.4. Forward Routing Filter

ForwardRoutingFilter 在 exchange 属性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 中寻找一个URI。如果URL有一个 forward scheme(如 forward:///localendpoint),它就使用 Spring DispatcherHandler 来处理请求。请求URL的路径部分被前向URL中的路径所覆盖。未修改的原始URL被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性的列表中。

7.5. Netty Routing Filter

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange 属性中的URL有一个 http 或 https scheme,Netty 路由过滤器就会运行。它使用Netty HttpClient 来进行下游代理请求。响应被放在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange 属性中,供以后的过滤器使用。(还有一个实验性的 WebClientHttpRoutingFilter,执行同样的功能,但不需要 Netty。)

7.6. Netty Write Response Filter

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

7.7. ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter 在名为 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的 exchange 属性中寻找一个URI。如果URL有一个 lb scheme(如 lb://myservice),它将使用Spring Cloud ReactorLoadBalancer 将名称(本例中为 myservice)解析为实际的主机和端口,并替换同一属性中的URI。未修改的原始URL被追加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 属性的列表中。过滤器也会在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 属性中查看是否等于 lb,如果是,同样的规则也适用。下面的列表配置了一个 ReactiveLoadBalancerClientFilter。

Example 65. application.yml

spring:

cloud:

gateway:

routes:

- id: myRoute

uri: lb://service

predicates:

- Path=/service/**

默认情况下,当 ReactorLoadBalancer 无法找到一个服务实例时,会返回 503。你可以通过设置 spring.cloud.gateway.loadbalancer.use404=true,将网关配置为返回 404。

从 ReactiveLoadBalancerClientFilter 返回的 ServiceInstance 的 isSecure 值覆盖了向网关发出的请求中指定的scheme。例如,如果请求通过 HTTPS 进入Gateway,但 ServiceInstance 表示它不安全,那么下游请求将通过 HTTP 进行。相反的情况也可以适用。然而,如果在网关配置中为路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,那么前缀将被剥离,来自路由 URL 的结果scheme将覆盖 ServiceInstance 的配置。

Gateway 支持所有的 LoadBalancer 功能。你可以在 Spring Cloud Commons 文档中阅读更多关于它们的信息。

7.8. RouteToRequestUrl Filter

如果在 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange 属性中有一个 Route 对象,RouteToRequestUrlFilter 会运行。它创建了一个新的URI,基于请求URI,但用 Route 对象的URI属性进行更新。新的URI被放在 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange 属性中。

如果URI有一个scheme 前缀(prefix),比如 lb:ws://serviceid,lb scheme就会从URI中剥离出来,放在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 中,以便以后在过滤器链中使用。

7.9. Websocket Routing Filter

如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange 属性中的URL有 ws 或 wss scheme,则运行 websocket 路由过滤器。它使用Spring WebSocket 基础设施将 websocket 请求转发到下游。

你可以通过给URI加上 lb 的前缀来实现websockets的负载均衡,比如 lb:ws://serviceid。

如果你使用 SockJS 作为普通HTTP的后备方案,你应该配置一个普通的HTTP路由以及websocket路由。

下面配置了一个websocket路由过滤器。

Example 66. application.yml

spring:

cloud:

gateway:

routes:

# SockJS route

- id: websocket_sockjs_route

uri: http://localhost:3001

predicates:

- Path=/websocket/info/**

# Normal Websocket route

- id: websocket_route

uri: ws://localhost:3001

predicates:

- Path=/websocket/**

7.10. 标记 exchange 为已路由

在网关路由了一个 ServerWebExchange 后,它通过在 exchange 属性中添加 gatewayAlreadyRouted 来标记该交换为 “routed” 。一旦一个请求被标记为已路由,其他路由过滤器就不会再对该请求进行路由,基本上是跳过过滤器。有一些方便的方法,你可以用来标记一个 exchange 为已路由,或者检查一个 exchange 是否已经被路由。

ServerWebExchangeUtils.isAlreadyRouted 接收一个 ServerWebExchange 对象并检查它是否已经被 "路由"。

ServerWebExchangeUtils.setAlreadyRouted 接收一个 ServerWebExchange 对象并将其标记为 "已路由"。

8. HttpHeadersFilter

HttpHeadersFilter 在向下游发送请求之前被应用于请求,例如在 NettyRoutingFilter。

8.1. Forwarded Headers Filter

Forwarded Headers Filter 创建一个 Forwarded header来发送给下游服务。它将当前请求的 Host header、scheme和port添加到任何现有的 Forwarded 头中。

8.2. RemoveHopByHop Headers Filter

RemoveHopByHop Headers Filter 从转发的请求中移除header信息。被移除的header信息的默认列表来自 IETF。

默认删除的header是:

Connection

Keep-Alive

Proxy-Authenticate

Proxy-Authorization

TE

Trailer

Transfer-Encoding

Upgrade

要改变这一点,请将 spring.cloud.gateway.filter.remove-hop-by-hop.headers 属性设置为要删除的 header 名称列表。

8.3. XForwarded Headers Filter

XForwarded Headers Filter 创建各种 X-Forwarded-* 头,以发送到下游的服务。它使用当前请求的 Host header、scheme、port 和路径来创建各种 header。

创建单个 header 可以由以下布尔属性控制(默认为 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

附加多个 header 可以由以下布尔属性控制(默认为 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

9. TLS 和 SSL

网关可以通过遵循通常的 Spring server configuration 来监听 HTTPS 请求。下面的例子显示了如何做到这一点。

Example 67. application.yml

server:

ssl:

enabled: true

key-alias: scg

key-store-password: scg1234

key-store: classpath:scg-keystore.p12

key-store-type: PKCS12

你可以将网关路由到HTTP和HTTPS后端。如果你要路由到HTTPS后端,你可以通过以下配置将网关配置为信任所有下游的证书。

Example 68. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

useInsecureTrustManager: true

使用不安全的 trust manager 不适合于生产。对于生产部署,你可以用一组已知的证书来配置网关,它可以通过以下配置来信任。

Example 69. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

trustedX509Certificates:

- cert1.pem

- cert2.pem

如果 Spring Cloud Gateway 没有配置受信任的证书,就会使用默认的 trust store(你可以通过设置 javax.net.ssl.trustStore 系统属性来覆盖它)。

9.1. TLS 握手

网关维护着一个client pool,它用来路由到后端。当通过HTTPS进行通信时,客户端发起了一个TLS握手。一些 timeout 配置与这个握手相关。你可以对这些 timeouts 进行配置,如下(默认值)。

Example 70. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

handshake-timeout-millis: 10000

close-notify-flush-timeout-millis: 3000

close-notify-read-timeout-millis: 0

10. 配置(Configuration)

Spring Cloud Gateway 的配置是由 RouteDefinitionLocator 实例的集合驱动的。下面的列表显示了 RouteDefinitionLocator 接口的定义。

Example 71. RouteDefinitionLocator.java

public interface RouteDefinitionLocator {

Flux getRouteDefinitions();

}

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

前面的配置例子都使用了一种快捷方式,即使用位置参数而不是命名参数。下面的两个例子是等价的。

Example 72. application.yml

spring:

cloud:

gateway:

routes:

- id: setstatus_route

uri: https://example.org

filters:

- name: SetStatus

args:

status: 401

- id: setstatusshortcut_route

uri: https://example.org

filters:

- SetStatus=401

对于网关的某些用途来说,属性已经足够了,但一些生产用例会从外部来源(如数据库)加载配置中受益。未来的里程碑版本将有基于 Spring Data Repository 的 RouteDefinitionLocator 实现,如 Redis、MongoDB和Cassandra。

10.1. RouteDefinition 指标

要启用 RouteDefinition 指标,请添加 spring-boot-starter-actuator 依赖。然后,默认情况下,只要 spring.cloud.gateway.metrics.enabled 属性被设置为 true,这些指标就会可用。将添加一个名为 spring.cloud.gateway.routes.count 的指标,其值是 RouteDefinitions 的数量。这个指标将从 /actuator/metrics/spring.cloud.gateway.routes.count 中获得。

11. 路由元数据配置

你可以通过使用元数据为每个路由配置额外的参数,如下所示。

Example 73. application.yml

spring:

cloud:

gateway:

routes:

- id: route_with_metadata

uri: https://example.org

metadata:

optionName: "OptionValue"

compositeObject:

name: "value"

iAmNumber: 1

你可以从一个 exchange 所获取所有的元数据属性,如下所示

Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);

// get all metadata properties

route.getMetadata();

// get a single metadata property

route.getMetadata(someKey);

12. Http超时(timeout)配置

可以为所有路由配置Http超时(响应和连接),也可以为每个特定的路由重写。

12.1. 全局 timeout

要配置全局http超时。

connect-timeout 必须以毫秒为单位指定。

响应超时必须以 java.time.Duration 的形式指定。

global http timeouts example

spring:

cloud:

gateway:

httpclient:

connect-timeout: 1000

response-timeout: 5s

12.2. 每个路由的 timeout

要配置每个路由的超时。

connect-timeout 必须以毫秒为单位指定。

response-timeout 必须以毫秒为单位指定。

per-route http timeouts configuration via configuration

- id: per_route_timeouts

uri: https://example.org

predicates:

- name: Path

args:

pattern: /delay/{timeout}

metadata:

response-timeout: 200

connect-timeout: 200

per-route timeouts configuration using Java DSL

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR;

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR;

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){

return routeBuilder.routes()

.route("test1", r -> {

return r.host("*.somehost.org").and().path("/somepath")

.filters(f -> f.addRequestHeader("header1", "header-value-1"))

.uri("http://someuri")

.metadata(RESPONSE_TIMEOUT_ATTR, 200)

.metadata(CONNECT_TIMEOUT_ATTR, 200);

})

.build();

}

路由的 response-timeout 为负值,将禁用全局 response-timeout 值。

- id: per_route_timeouts

uri: https://example.org

predicates:

- name: Path

args:

pattern: /delay/{timeout}

metadata:

response-timeout: -1

12.3. Route 的Fluent式 Java API

为了允许在Java中进行简单的配置,RouteLocatorBuilder Bean包括一个fluent API。下面的列表显示了它是如何工作的。

Example 74. GatewaySampleApplication.java

// static imports from GatewayFilters and RoutePredicates

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {

return builder.routes()

.route(r -> r.host("**.abc.org").and().path("/image/png")

.filters(f ->

f.addResponseHeader("X-TestHeader", "foobar"))

.uri("http://httpbin.org:80")

)

.route(r -> r.path("/image/webp")

.filters(f ->

f.addResponseHeader("X-AnotherHeader", "baz"))

.uri("http://httpbin.org:80")

.metadata("key", "value")

)

.route(r -> r.order(-1)

.host("**.throttle.org").and().path("/get")

.filters(f -> f.filter(throttle.apply(1,

1,

10,

TimeUnit.SECONDS)))

.uri("http://httpbin.org:80")

.metadata("key", "value")

)

.build();

}

这种风格也允许更多的自定义谓词断言。RouteDefinitionLocator bean 类定义的谓词使用逻辑 and 来组合。通过使用fluent Java API,你可以在 Predicate 类上使用 and()、or() 和 negate() 操作符。

12.4. DiscoveryClient 路由服务的注册与发现

你可以将网关配置为基于在 DiscoveryClient 兼容服务注册中心上注册的服务来创建路由。

要启用这一点,请设置 spring.cloud.gateway.discovery.locator.enabled=true 并确保 DiscoveryClient 实现(如 Netflix Eureka、Consul 或 Zookeeper)位于 classpath 上并已启用。

12.4.1. 为 DiscoveryClient 路由配置谓词和过滤器

默认情况下,网关为用 DiscoveryClient 创建的路由定义了一个谓词和过滤器。

默认谓词是用 /serviceId/** pattern 定义的路径谓词,其中 serviceId 是来自 DiscoveryClient 的服务的 ID。

默认的过滤器是一个重写路径过滤器,使用 regex /serviceId/?(?.*) 和替换词 /${remaining}。这在请求被发送到下游之前从路径中剥离了服务ID。

如果你想定制 DiscoveryClient 路由使用的谓词或过滤器,请设置 spring.cloud.gateway.discovery.locator.predicates[x] 和 spring.cloud.gateway.discovery.locator.filters[y]。这样做时,如果你想保留该功能,你需要确保包括前面显示的默认谓词和过滤器。下面的例子显示了这是什么样子。

Example 75. application.properties

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: CircuitBreaker

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 + '/?(?.*)'"

spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

13. Reactor Netty 访问日志

要启用 Reactor Netty 访问日志,请设置 -Dreactor.netty.http.server.accessLogEnabled=true。

它必须是一个 Java System Property,而不是一个Spring Boot属性。

你可以配置日志系统,使其有一个单独的访问日志文件。下面的例子创建了一个Logback配置。

Example 76. logback.xml

access_log.log

%msg%n

14. CORS 配置

你可以配置网关来控制全局或每个路由的 CORS 行为。两者都提供同样的可能性。

14.1. Global CORS 配置

“global” CORS配置是对 Spring Framework CorsConfiguration 的URL模式的映射。下面的例子配置了 CORS。

Example 77. application.yml

spring:

cloud:

gateway:

globalcors:

cors-configurations:

'[/**]':

allowedOrigins: "https://docs.spring.io"

allowedMethods:

- GET

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

要为未被某些网关路由谓词处理的请求提供相同的 CORS 配置,请将 spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping 属性设为 true。当你试图支持 CORS 预检请求,而你的路由谓词因为 HTTP 方法是 options 而不能评估为 true 时,这很有用。

14.2. 路由的 CORS 配置

“route” configuration 允许将CORS直接应用于带有key CORS 的路由作为元数据。像全局配置一样,这些属性属于 Spring Framework CorsConfiguration。

如果路由中没有 Path 谓词,则将应用 '/**'。

Example 78. application.yml

spring:

cloud:

gateway:

routes:

- id: cors_route

uri: https://example.org

predicates:

- Path=/service/**

metadata:

cors

allowedOrigins: '*'

allowedMethods:

- GET

- POST

allowedHeaders: '*'

maxAge: 30

15. Actuator API

通过 /gateway 执行器端点,你可以监控并与 Spring Cloud Gateway 应用进行互动。要进行远程访问,端点必须在应用程序属性中 enabled 并 通过HTTP或JMX暴露。下面的列表显示了如何做到这一点。

Example 79. application.properties

management.endpoint.gateway.enabled=true # default value

management.endpoints.web.exposure.include=gateway

15.1. 冗长的 Actuator 格式

在Spring Cloud Gateway中增加了一种新的、更啰嗦的格式。它为每个路由添加了更多细节,让你查看与每个路由相关的谓词和过滤器,以及任何可用的配置。下面的例子配置了 /actuator/gateway/routes。

[

{

"predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",

"route_id": "add_request_header_test",

"filters": [

"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",

"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",

"[[PrefixPath prefix = '/httpbin'], order = 2]"

],

"uri": "lb://testservice",

"order": 0

}

]

这个功能默认是启用的。要禁用它,请设置以下属性。

Example 80. application.properties

spring.cloud.gateway.actuator.verbose.enabled=false

在未来的版本中,这将默认为 true。

15.2. 检索路由过滤器

本节详细介绍了如何检索路由过滤器,包括:

全局过滤器(Global Filter)

[gateway-route-filters]

15.2.1. 全局过滤器(Global Filter)

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

{

"org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5": 10100,

"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,

"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,

"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,

"org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647,

"org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0,

"org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,

"org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646

}

响应包含全局过滤器的细节,这些过滤器已经到位。对于每个全局过滤器,有一个过滤器对象的字符串表示(例如,org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5)以及过滤器链中的相应 顺序。

15.2.2. 路由过滤器(Route Filter)

要检索应用于路由的 GatewayFilter 工厂,请向 /actuator/gateway/routefilters 发出一个 GET 请求。得到的响应类似于以下内容。

{

"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,

"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,

"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null

}

响应包含应用于任何特定路由的 GatewayFilter 工厂的细节。对于每个工厂,有一个相应对象的字符串表示(例如,[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,nul 是由于 endpoint controller 的不完整实现,因为它试图设置过滤器链中的对象的顺序,这不适用于 GatewayFilter 工厂对象。

15.3. 刷新路由缓存

要清除路由缓存,请向 /actuator/gateway/refresh 发出一个 POST 请求。该请求返回一个200,没有响应体。

15.4. 检索网关中自定义的路由

要检索网关中定义的路由,请向 /actuator/gateway/routes 发出一个 GET 请求。得到的响应类似于以下内容。

[{

"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

}]

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

Path

Type

Description

route_id

String

路由 ID。

route_object.predicate

Object

路由的 predicate。

route_object.filters

Array

应用于路由的 GatewayFilter 工厂。

order

Number

路由顺序。

15.5. 检索指定的路由

要检索一条路由的信息,请向 /actuator/gateway/routes/{id} 发出一个 GET 请求(例如,/actuator/gateway/routes/first_route)。得到的响应类似于下面的内容。

{

"id": "first_route",

"predicates": [{

"name": "Path",

"args": {"_genkey_0":"/first"}

}],

"filters": [],

"uri": "https://www.uri-destination.org",

"order": 0

}

下表描述了响应的结构。

Path

Type

Description

id

String

路由 ID。

predicates

Array

路由谓词的集合。每一项都定义了谓词的名称和参数。

filters

Array

应用于路由的Filter集合。

uri

String

路由的目的地URI。

order

Number

路由的Order。

15.6. 创建和删除一个指定的路由

要创建一个路由,请向 /gateway/routes/{id_route_to_create} 发出一个 POST 请求,该请求包含一个指定路由字段的JSON BODY(见 检索指定的路由)。

要删除一条路由,请向 /gateway/routes/{id_route_to_delete} 发出 DELETE 请求。

15.7. 回顾:所有端点列表

下面的表格总结了 Spring Cloud Gateway 的执行器(actuator)端点(注意,每个端点都有 /actuator/gateway 作为基本路径)。

ID

HTTP Method

Description

globalfilters

GET

显示应用于路由的全局过滤器的列表。

routefilters

GET

显示应用于特定路由的 GatewayFilter 工厂的列表。

refresh

POST

清除路由缓存。

routes

GET

显示网关中定义的路由列表。

routes/{id}

GET

显示指定路由的信息。

routes/{id}

POST

添加一个新的路由到网关。

routes/{id}

DELETE

从网关删除一个路由。

15.8. 在多个网关实例之间共享路由

Spring Cloud Gateway 提供两种 RouteDefinitionRepository 实现。第一个是 InMemoryRouteDefinitionRepository,它只存在于一个 Gateway 实例的内存中。这种类型的 Repository 不适合在多个Gateway实例中填充路由。

为了在 Spring Cloud Gateway 实例的集群中共享路由,可以使用 RedisRouteDefinitionRepository。要启用这种 repository,必须将以下属性设置为 true: spring.cloud.gateway.redis-route-definition-repository.enabled。与 RedisRateLimiter 过滤器工厂一样,它需要使用 spring-boot-starter-data-redis-reactive Spring Boot starter。

16. 问题排查

本节涵盖了你在使用 Spring Cloud Gateway 时可能出现的常见问题。

16.1. 日志级别

在 DEBUG 和 TRACE 级别,以下logger可能包含有价值的故障排除信息。

org.springframework.cloud.gateway

org.springframework.http.server.reactive

org.springframework.web.reactive

org.springframework.boot.autoconfigure.web

reactor.netty

redisratelimiter

16.2. Wiretap

Reactor Netty 的 HttpClient 和 HttpServer 可以启用 wiretap。当与 reactor.netty 日志级别设置为 DEBUG 或 TRACE 相结合时,它能够记录信息,例如通过路由发送和接收的header信息和body。要启用 wiretap,请分别为 HttpServer 和 HttpClient 设置 spring.cloud.gateway.httpserver.wiretap=true 或 spring.cloud.gateway.httpclient.wiretap=true。

17. 开发手册

这些是编写网关的一些自定义组件的基本指南。

17.1. 编写自定义路由(Route)谓语(Predicate)工厂

自定义 Route Predicate,你需要提供一个实现了 RoutePredicateFactory 的 bean。有一个抽象的类叫做 AbstractRoutePredicateFactory,你可以继承它。

MyRoutePredicateFactory.java

@Component

public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {

public MyRoutePredicateFactory() {

super(Config.class);

}

@Override

public Predicate apply(Config config) {

// grab configuration from Config object

return exchange -> {

//grab the request

ServerHttpRequest request = exchange.getRequest();

//take information from the request to see if it

//matches configuration.

return matches(config, request);

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

17.2. 编写自定义 GatewayFilter 工厂

自定义 GatewayFilter,你必须提供一个实现了 GatewayFilterFactory 的bean。你可以继承一个名为 AbstractGatewayFilterFactory 的抽象类。下面的例子展示了如何做到这一点。

Example 81. PreGatewayFilterFactory.java

@Component

public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PreGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

//If you want to build a "pre" filter you need to manipulate the

//request before calling chain.filter

ServerHttpRequest.Builder builder = exchange.getRequest().mutate();

//use builder to manipulate the request

return chain.filter(exchange.mutate().request(builder.build()).build());

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

PostGatewayFilterFactory.java

@Component

public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PostGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

ServerHttpResponse response = exchange.getResponse();

//Manipulate the response in some way

}));

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

17.2.1. 在配置中命名自定义 Filter 和引用

自定义Filter的类名应该以 GatewayFilterFactory 结尾。

例如,要在配置文件中引用一个名为 Something 的过滤器,该过滤器必须在一个名为 SomethingGatewayFilterFactory 的类中。

可以创建一个没有 GatewayFilterFactory 后缀的网关过滤器,如 AnotherThing 类。这个过滤器可以在配置文件中被引用为 AnotherThing。这不是一个被支持的命名惯例,这种语法可能在未来的版本中被删除。请更新过滤器的名称,使其符合要求。

17.3. 编写自定义全局过滤器

要编写一个自定义的全局过滤器,你必须提供一个实现了 GlobalFilter 接口的Bean。这将把过滤器应用于所有的请求。

下面的例子分别说明了如何设置全局 pre 过滤器和 post 过滤器。

@Bean

public GlobalFilter customGlobalFilter() {

return (exchange, chain) -> exchange.getPrincipal()

.map(Principal::getName)

.defaultIfEmpty("Default User")

.map(userName -> {

//adds header to proxied request

exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();

return exchange;

})

.flatMap(chain::filter);

}

@Bean

public GlobalFilter customGlobalPostFilter() {

return (exchange, chain) -> chain.filter(exchange)

.then(Mono.just(exchange))

.map(serverWebExchange -> {

//adds header to response

serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",

HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");

return serverWebExchange;

})

.then();

}

18. 通过使用Spring MVC或Webflux构建一个简单的网关

下面描述的是另一种风格的网关。之前的文档都不适用于下面的内容。

Spring Cloud Gateway 提供了一个名为 ProxyExchange 的实用对象。你可以在普通的 Spring web handler 中作为方法参数使用它。它通过反映 HTTP 动词的方法支持基本的下游 HTTP exchange。在MVC中,它还支持通过 forward() 方法转发到本地处理程序。要使用 ProxyExchange,在你的classpath中包含正确的模块(spring-cloud-gateway-mvc 或 spring-cloud-gateway-webflux)。

下面的MVC例子将一个到 /test 的请求代理到一个远程服务器。

@RestController

@SpringBootApplication

public class GatewaySampleApplication {

@Value("${remote.home}")

private URI home;

@GetMapping("/test")

public ResponseEntity proxy(ProxyExchange proxy) throws Exception {

return proxy.uri(home.toString() + "/image/png").get();

}

}

下面的例子用Webflux实现相同的效果。

@RestController

@SpringBootApplication

public class GatewaySampleApplication {

@Value("${remote.home}")

private URI home;

@GetMapping("/test")

public Mono> proxy(ProxyExchange proxy) throws Exception {

return proxy.uri(home.toString() + "/image/png").get();

}

}

ProxyExchange 上的便利方法使处理方法能够发现并增强传入请求的URI路径。例如,你可能想提取路径的尾部元素,将它们传递到下游。

@GetMapping("/proxy/path/**")

public ResponseEntity proxyPath(ProxyExchange proxy) throws Exception {

String path = proxy.path("/proxy/path/");

return proxy.uri(home.toString() + "/foos/" + path).get();

}

Spring MVC和Webflux的所有功能都可用于网关 handler method。因此,你可以注入请求头和查询参数,例如,你可以通过 mapping 注解中的声明来限制传入的请求。关于这些功能的更多细节,请参见Spring MVC中的 @RequestMapping 文档。

你可以通过使用 ProxyExchange 的 header() 方法在下游响应中添加头信息。

你也可以通过给 get() 方法(和其他方法)添加一个 mapper 来操作响应头(以及 response 中你喜欢的其他东西)。mapper 是一个 Function,它接收传入的 ResponseEntity 并将其转换为传出的。

对 "敏感" header(默认为 cookie 和 授 authorization)和 “proxy”(x-forwarded-*)header 提供了一流的支持,这些标头不会被传递到下游。

19. AOT 和 原生镜像(Native Image)的支持

从 4.0.0 开始,Spring Cloud Gateway支持 Spring AOT 转换和原生镜像。

如果你使用负载均衡路由,你需要明确定义你的 LoadBalancerClient 服务 ID。你可以通过使用 @LoadBalancerClient 注解的 value 或 name 属性或作为 spring.cloud.loadbalancer.eager-load.clients 属性的值来实现。

20. 配置属性

要查看所有与Spring Cloud Gateway相关的配置属性列表,请参见 附录。

Spring Cloud Gateway

ng Cloud GatewaySkip to main contentWhy SpringOverviewMicroservicesReactiveEvent DrivenCloudWeb ApplicationsServerlessBatchLearnOverviewQuickstartGuidesBlogProjectsOverviewSpring BootSpring FrameworkSpring CloudSpring Cloud Data FlowSpring DataSpring IntegrationSpring BatchSpring SecurityView all projectsDEVELOPMENT TOOLSSpring Tools 4Spring InitializrAcademyCoursesGet CertifiedSolutionsOverviewTanzu Spring RuntimeSpring ConsultingSpring Academy For TeamsSecurity AdvisoriesCommunityOverviewEventsTeamSpring BootSpring FrameworkSpring DataSpring CloudSpring Cloud AzureSpring Cloud AlibabaSpring Cloud for Amazon Web ServicesSpring Cloud BusSpring Cloud Circuit BreakerSpring Cloud CLISpring Cloud - Cloud Foundry Service BrokerSpring Cloud CommonsSpring Cloud ConfigSpring Cloud ConsulSpring Cloud ContractSpring Cloud FunctionSpring Cloud GatewaySpring Cloud GCPSpring Cloud KubernetesSpring Cloud NetflixSpring Cloud Open Service BrokerSpring Cloud OpenFeignSpring Cloud SecuritySpring Cloud SkipperSpring Cloud SleuthSpring Cloud StreamSpring Cloud Stream ApplicationsSpring Cloud TaskSpring Cloud VaultSpring Cloud ZookeeperSpring Cloud App BrokerSpring Cloud Data FlowSpring SecuritySpring Authorization ServerSpring for GraphQLSpring SessionSpring IntegrationSpring HATEOASSpring ModulithSpring REST DocsSpring AISpring BatchSpring CLISpring AMQPSpring CredHubSpring FloSpring for Apache KafkaSpring LDAPSpring for Apache PulsarSpring ShellSpring StatemachineSpring VaultSpring Web FlowSpring Web ServicesSpring Cloud Gateway4.1.1OverviewLearnSupportSamplesThis project provides a libraries for building an API Gateway on top of Spring WebFlux or Spring WebMVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

Features

Spring Cloud Gateway features:

Built on Spring Framework and Spring Boot

Able to match routes on any request attribute.

Predicates and filters are specific to routes.

Circuit Breaker integration.

Spring Cloud DiscoveryClient integration

Easy to write Predicates and Filters

Request Rate Limiting

Path Rewriting

Getting Started

@SpringBootApplication

public class DemogatewayApplication {

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

return builder.routes()

.route("path_route", r -> r.path("/get")

.uri("http://httpbin.org"))

.route("host_route", r -> r.host("*.myhost.org")

.uri("http://httpbin.org"))

.route("rewrite_route", r -> r.host("*.rewrite.org")

.filters(f -> f.rewritePath("/foo/(?.*)", "/${segment}"))

.uri("http://httpbin.org"))

.route("hystrix_route", r -> r.host("*.hystrix.org")

.filters(f -> f.hystrix(c -> c.setName("slowcmd")))

.uri("http://httpbin.org"))

.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")

.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))

.uri("http://httpbin.org"))

.route("limit_route", r -> r

.host("*.limited.org").and().path("/anything/**")

.filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))

.uri("http://httpbin.org"))

.build();

}

}

To run your own gateway use the spring-cloud-starter-gateway dependency.Quickstart Your ProjectBootstrap your application with Spring Initializr.Get aheadVMware offers training and certification to turbo-charge your progress.Learn moreGet supportTanzu Spring Runtime offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.Learn moreUpcoming eventsCheck out all the upcoming events in the Spring community.View allWhy SpringMicroservicesReactiveEvent DrivenCloudWeb ApplicationsServerlessBatchLearnQuickstartGuidesBlogCommunityEventsTeamSolutionsTanzu Spring RuntimeSpring ConsultingSpring Academy For TeamsSpring AdvisoriesProjectsTrainingThank YouGet the Spring newsletterThank you for your interest. Someone will get back to you shortly.Copyright © 2005 - 2024 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. Terms of Use • Privacy • Trademark Guidelines • Your California Privacy Rights • Cookie SettingsApache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.

Spring Cloud Gateway

Spring Cloud Gateway

Dark Theme

Spring Cloud Gateway

Table of Contents

1. How to Include Spring Cloud Gateway

2. Glossary

3. How It Works

4. Configuring Route Predicate Factories and Gateway Filter Factories

4.1. Shortcut Configuration

4.2. Fully Expanded Arguments

5. Route Predicate Factories

5.1. The After Route Predicate Factory

5.2. The Before Route Predicate Factory

5.3. The Between Route Predicate Factory

5.4. The Cookie Route Predicate Factory

5.5. The Header Route Predicate Factory

5.6. The Host Route Predicate Factory

5.7. The Method Route Predicate Factory

5.8. The Path Route Predicate Factory

5.9. The Query Route Predicate Factory

5.10. The RemoteAddr Route Predicate Factory

5.10.1. Modifying the Way Remote Addresses Are Resolved

5.11. The Weight Route Predicate Factory

5.12. The XForwarded Remote Addr Route Predicate Factory

6. GatewayFilter Factories

6.1. The AddRequestHeader GatewayFilter Factory

6.2. The AddRequestHeadersIfNotPresent GatewayFilter Factory

6.3. The AddRequestParameter GatewayFilter Factory

6.4. The AddResponseHeader GatewayFilter Factory

6.5. The CircuitBreaker GatewayFilter Factory

6.5.1. Tripping The Circuit Breaker On Status Codes

6.6. The CacheRequestBody GatewayFilter Factory

6.7. The DedupeResponseHeader GatewayFilter Factory

6.8. The FallbackHeaders GatewayFilter Factory

6.9. The JsonToGrpc GatewayFilter Factory

6.10. The LocalResponseCache GatewayFilter Factory

6.11. The MapRequestHeader GatewayFilter Factory

6.12. The ModifyRequestBody GatewayFilter Factory

6.13. The ModifyResponseBody GatewayFilter Factory

6.14. The PrefixPath GatewayFilter Factory

6.15. The PreserveHostHeader GatewayFilter Factory

6.16. The RedirectTo GatewayFilter Factory

6.17. RemoveJsonAttributesResponseBody GatewayFilter Factory

6.18. The RemoveRequestHeader GatewayFilter Factory

6.19. The RemoveRequestParameter GatewayFilter Factory

6.20. The RemoveResponseHeader GatewayFilter Factory

6.21. The RequestHeaderSize GatewayFilter Factory

6.22. The RequestRateLimiter GatewayFilter Factory

6.22.1. The Redis RateLimiter

6.23. The RewriteLocationResponseHeader GatewayFilter Factory

6.24. The RewritePath GatewayFilter Factory

6.25. The RewriteRequestParameter GatewayFilter Factory

6.26. The RewriteResponseHeader GatewayFilter Factory

6.27. The SaveSession GatewayFilter Factory

6.28. The SecureHeaders GatewayFilter Factory

6.29. The SetPath GatewayFilter Factory

6.30. The SetRequestHeader GatewayFilter Factory

6.31. The SetResponseHeader GatewayFilter Factory

6.32. The SetStatus GatewayFilter Factory

6.33. The StripPrefix GatewayFilter Factory

6.34. The Retry GatewayFilter Factory

6.35. The RequestSize GatewayFilter Factory

6.36. The SetRequestHostHeader GatewayFilter Factory

6.37. The TokenRelay GatewayFilter Factory

6.38. Default Filters

7. Global Filters

7.1. Combined Global Filter and GatewayFilter Ordering

7.2. The Gateway Metrics Filter

7.3. The Local Response Cache Filter

7.4. Forward Routing Filter

7.5. The Netty Routing Filter

7.6. The Netty Write Response Filter

7.7. The ReactiveLoadBalancerClientFilter

7.8. The RouteToRequestUrl Filter

7.9. The Websocket Routing Filter

7.10. Marking An Exchange As Routed

8. HttpHeadersFilters

8.1. Forwarded Headers Filter

8.2. RemoveHopByHop Headers Filter

8.3. XForwarded Headers Filter

9. TLS and SSL

9.1. TLS Handshake

10. Configuration

10.1. RouteDefinition Metrics

11. Route Metadata Configuration

12. Http timeouts configuration

12.1. Global timeouts

12.2. Per-route timeouts

13. Fluent Java Routes API

14. The DiscoveryClient Route Definition Locator

14.1. Configuring Predicates and Filters For DiscoveryClient Routes

15. Reactor Netty Access Logs

16. CORS Configuration

16.1. Global CORS Configuration

16.2. Route CORS Configuration

17. Actuator API

17.1. Verbose Actuator Format

17.2. Retrieving Route Filters

17.2.1. Global Filters

17.2.2. Route Filters

17.3. Refreshing the Route Cache

17.4. Retrieving the Routes Defined in the Gateway

17.5. Retrieving Information about a Particular Route

17.6. Creating and Deleting a Particular Route Definition

17.7. Creating multiple Route Definitions

17.8. Recap: The List of All endpoints

17.9. Sharing Routes between multiple Gateway instances

18. Troubleshooting

18.1. Log Levels

18.2. Wiretap

19. Developer Guide

19.1. Writing Custom Route Predicate Factories

19.2. Writing Custom GatewayFilter Factories

19.2.1. Naming Custom Filters And References In Configuration

19.3. Writing Custom Global Filters

20. Building a Simple Gateway by Using Spring MVC or Webflux

21. AOT and Native Image Support

22. Configuration properties

4.0.9

This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 6, Spring Boot 3 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

1. How to Include Spring Cloud Gateway

To include Spring Cloud Gateway in your project, use the starter with a group ID of org.springframework.cloud and an artifact ID of spring-cloud-starter-gateway.

See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.

If you include the starter, but you do not want the gateway to be enabled, set spring.cloud.gateway.enabled=false.

Spring Cloud Gateway is built on Spring Boot, Spring WebFlux, and Project Reactor.

As a consequence, many of the familiar synchronous libraries (Spring Data and Spring Security, for example) and patterns you know may not apply when you use Spring Cloud Gateway.

If you are unfamiliar with these projects, we suggest you begin by reading their documentation to familiarize yourself with some new concepts before working with Spring Cloud Gateway.

Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux.

It does not work in a traditional Servlet Container or when built as a WAR.

2. Glossary

Route: The basic building block of the gateway.

It is defined by an ID, a destination URI, a collection of predicates, and a collection of filters. A route is matched if the aggregate predicate is true.

Predicate: This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange.

This lets you match on anything from the HTTP request, such as headers or parameters.

Filter: These are instances of GatewayFilter that have been constructed with a specific factory.

Here, you can modify requests and responses before or after sending the downstream request.

3. How It Works

The following diagram provides a high-level overview of how Spring Cloud Gateway works:

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler.

This handler runs the request through a filter chain that is specific to the request.

The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent.

All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.

URIs defined in routes without a port get default port values of 80 and 443 for the HTTP and HTTPS URIs, respectively.

4. Configuring Route Predicate Factories and Gateway Filter Factories

There are two ways to configure predicates and filters: shortcuts and fully expanded arguments. Most examples below use the shortcut way.

The name and argument names are listed as code in the first sentence or two of each section. The arguments are typically listed in the order that are needed for the shortcut configuration.

4.1. Shortcut Configuration

Shortcut configuration is recognized by the filter name, followed by an equals sign (=), followed by argument values separated by commas (,).

application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- Cookie=mycookie,mycookievalue

The previous sample defines the Cookie Route Predicate Factory with two arguments, the cookie name, mycookie and the value to match mycookievalue.

4.2. Fully Expanded Arguments

Fully expanded arguments appear more like standard yaml configuration with name/value pairs. Typically, there will be a name key and an args key. The args key is a map of key value pairs to configure the predicate or filter.

application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- name: Cookie

args:

name: mycookie

regexp: mycookievalue

This is the full configuration of the shortcut configuration of the Cookie predicate shown above.

5. Route Predicate Factories

Spring Cloud Gateway matches routes as part of the Spring WebFlux HandlerMapping infrastructure.

Spring Cloud Gateway includes many built-in route predicate factories.

All of these predicates match on different attributes of the HTTP request.

You can combine multiple route predicate factories with logical and statements.

5.1. The After Route Predicate Factory

The After route predicate factory takes one parameter, a datetime (which is a java ZonedDateTime).

This predicate matches requests that happen after the specified datetime.

The following example configures an after route predicate:

Example 1. application.yml

spring:

cloud:

gateway:

routes:

- id: after_route

uri: https://example.org

predicates:

- After=2017-01-20T17:42:47.789-07:00[America/Denver]

This route matches any request made after Jan 20, 2017 17:42 Mountain Time (Denver).

5.2. The Before Route Predicate Factory

The Before route predicate factory takes one parameter, a datetime (which is a java ZonedDateTime).

This predicate matches requests that happen before the specified datetime.

The following example configures a before route predicate:

Example 2. application.yml

spring:

cloud:

gateway:

routes:

- id: before_route

uri: https://example.org

predicates:

- Before=2017-01-20T17:42:47.789-07:00[America/Denver]

This route matches any request made before Jan 20, 2017 17:42 Mountain Time (Denver).

5.3. The Between Route Predicate Factory

The Between route predicate factory takes two parameters, datetime1 and datetime2

which are java ZonedDateTime objects.

This predicate matches requests that happen after datetime1 and before datetime2.

The datetime2 parameter must be after datetime1.

The following example configures a between route predicate:

Example 3. application.yml

spring:

cloud:

gateway:

routes:

- id: between_route

uri: https://example.org

predicates:

- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

This route matches any request made after Jan 20, 2017 17:42 Mountain Time (Denver) and before Jan 21, 2017 17:42 Mountain Time (Denver).

This could be useful for maintenance windows.

5.4. The Cookie Route Predicate Factory

The Cookie route predicate factory takes two parameters, the cookie name and a regexp (which is a Java regular expression).

This predicate matches cookies that have the given name and whose values match the regular expression.

The following example configures a cookie route predicate factory:

Example 4. application.yml

spring:

cloud:

gateway:

routes:

- id: cookie_route

uri: https://example.org

predicates:

- Cookie=chocolate, ch.p

This route matches requests that have a cookie named chocolate whose value matches the ch.p regular expression.

5.5. The Header Route Predicate Factory

The Header route predicate factory takes two parameters, the header and a regexp (which is a Java regular expression).

This predicate matches with a header that has the given name whose value matches the regular expression.

The following example configures a header route predicate:

Example 5. application.yml

spring:

cloud:

gateway:

routes:

- id: header_route

uri: https://example.org

predicates:

- Header=X-Request-Id, \d+

This route matches if the request has a header named X-Request-Id whose value matches the \d+ regular expression (that is, it has a value of one or more digits).

5.6. The Host Route Predicate Factory

The Host route predicate factory takes one parameter: a list of host name patterns.

The pattern is an Ant-style pattern with . as the separator.

This predicates matches the Host header that matches the pattern.

The following example configures a host route predicate:

Example 6. application.yml

spring:

cloud:

gateway:

routes:

- id: host_route

uri: https://example.org

predicates:

- Host=**.somehost.org,**.anotherhost.org

URI template variables (such as {sub}.myhost.org) are supported as well.

This route matches if the request has a Host header with a value of www.somehost.org or beta.somehost.org or www.anotherhost.org.

This predicate extracts the URI template variables (such as sub, defined in the preceding example) as a map of names and values and places it in the ServerWebExchange.getAttributes() with a key defined in ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE.

Those values are then available for use by GatewayFilter factories

5.7. The Method Route Predicate Factory

The Method Route Predicate Factory takes a methods argument which is one or more parameters: the HTTP methods to match.

The following example configures a method route predicate:

Example 7. application.yml

spring:

cloud:

gateway:

routes:

- id: method_route

uri: https://example.org

predicates:

- Method=GET,POST

This route matches if the request method was a GET or a POST.

5.8. The Path Route Predicate Factory

The Path Route Predicate Factory takes two parameters: a list of Spring PathMatcher patterns and an optional flag called matchTrailingSlash (defaults to true).

The following example configures a path route predicate:

Example 8. application.yml

spring:

cloud:

gateway:

routes:

- id: path_route

uri: https://example.org

predicates:

- Path=/red/{segment},/blue/{segment}

This route matches if the request path was, for example: /red/1 or /red/1/ or /red/blue or /blue/green.

If matchTrailingSlash is set to false, then request path /red/1/ will not be matched.

This predicate extracts the URI template variables (such as segment, defined in the preceding example) as a map of names and values and places it in the ServerWebExchange.getAttributes() with a key defined in ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE.

Those values are then available for use by GatewayFilter factories

A utility method (called get) is available to make access to these variables easier.

The following example shows how to use the get method:

Map uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);

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

5.9. The Query Route Predicate Factory

The Query route predicate factory takes two parameters: a required param and an optional regexp (which is a Java regular expression).

The following example configures a query route predicate:

Example 9. application.yml

spring:

cloud:

gateway:

routes:

- id: query_route

uri: https://example.org

predicates:

- Query=green

The preceding route matches if the request contained a green query parameter.

application.yml

spring:

cloud:

gateway:

routes:

- id: query_route

uri: https://example.org

predicates:

- Query=red, gree.

The preceding route matches if the request contained a red query parameter whose value matched the gree. regexp, so green and greet would match.

5.10. The RemoteAddr Route Predicate Factory

The RemoteAddr route predicate factory takes a list (min size 1) of sources, which are CIDR-notation (IPv4 or IPv6) strings, such as 192.168.0.1/16 (where 192.168.0.1 is an IP address and 16 is a subnet mask).

The following example configures a RemoteAddr route predicate:

Example 10. application.yml

spring:

cloud:

gateway:

routes:

- id: remoteaddr_route

uri: https://example.org

predicates:

- RemoteAddr=192.168.1.1/24

This route matches if the remote address of the request was, for example, 192.168.1.10.

5.10.1. Modifying the Way Remote Addresses Are Resolved

By default, the RemoteAddr route predicate factory uses the remote address from the incoming request.

This may not match the actual client IP address if Spring Cloud Gateway sits behind a proxy layer.

You can customize the way that the remote address is resolved by setting a custom RemoteAddressResolver.

Spring Cloud Gateway comes with one non-default remote address resolver that is based off of the X-Forwarded-For header, XForwardedRemoteAddressResolver.

XForwardedRemoteAddressResolver has two static constructor methods, which take different approaches to security:

XForwardedRemoteAddressResolver::trustAll returns a RemoteAddressResolver that always takes the first IP address found in the X-Forwarded-For header.

This approach is vulnerable to spoofing, as a malicious client could set an initial value for the X-Forwarded-For, which would be accepted by the resolver.

XForwardedRemoteAddressResolver::maxTrustedIndex takes an index that correlates to the number of trusted infrastructure running in front of Spring Cloud Gateway.

If Spring Cloud Gateway is, for example only accessible through HAProxy, then a value of 1 should be used.

If two hops of trusted infrastructure are required before Spring Cloud Gateway is accessible, then a value of 2 should be used.

Consider the following header value:

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

The following maxTrustedIndex values yield the following remote addresses:

maxTrustedIndex

result

[Integer.MIN_VALUE,0]

(invalid, IllegalArgumentException during initialization)

1

0.0.0.3

2

0.0.0.2

3

0.0.0.1

[4, Integer.MAX_VALUE]

0.0.0.1

The following example shows how to achieve the same configuration with Java:

Example 11. GatewayConfig.java

RemoteAddressResolver resolver = XForwardedRemoteAddressResolver

.maxTrustedIndex(1);

...

.route("direct-route",

r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")

.uri("https://downstream1")

.route("proxied-route",

r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")

.uri("https://downstream2")

)

5.11. The Weight Route Predicate Factory

The Weight route predicate factory takes two arguments: group and weight (an int). The weights are calculated per group.

The following example configures a weight route predicate:

Example 12. application.yml

spring:

cloud:

gateway:

routes:

- id: weight_high

uri: https://weighthigh.org

predicates:

- Weight=group1, 8

- id: weight_low

uri: https://weightlow.org

predicates:

- Weight=group1, 2

This route would forward ~80% of traffic to weighthigh.org and ~20% of traffic to weighlow.org

5.12. The XForwarded Remote Addr Route Predicate Factory

The XForwarded Remote Addr route predicate factory takes a list (min size 1) of sources, which are CIDR-notation (IPv4 or IPv6) strings, such as 192.168.0.1/16 (where 192.168.0.1 is an IP address and 16 is a subnet mask).

This route predicate allows requests to be filtered based on the X-Forwarded-For HTTP header.

This can be used with reverse proxies such as load balancers or web application firewalls where

the request should only be allowed if it comes from a trusted list of IP addresses used by those

reverse proxies.

The following example configures a XForwardedRemoteAddr route predicate:

Example 13. application.yml

spring:

cloud:

gateway:

routes:

- id: xforwarded_remoteaddr_route

uri: https://example.org

predicates:

- XForwardedRemoteAddr=192.168.1.1/24

This route matches if the X-Forwarded-For header contains, for example, 192.168.1.10.

6. GatewayFilter Factories

Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner.

Route filters are scoped to a particular route.

Spring Cloud Gateway includes many built-in GatewayFilter Factories.

For more detailed examples of how to use any of the following filters, take a look at the unit tests.

6.1. The AddRequestHeader GatewayFilter Factory

The AddRequestHeader GatewayFilter factory takes a name and value parameter.

The following example configures an AddRequestHeader GatewayFilter:

Example 14. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

filters:

- AddRequestHeader=X-Request-red, blue

This listing adds X-Request-red:blue header to the downstream request’s headers for all matching requests.

AddRequestHeader is aware of the URI variables used to match a path or host.

URI variables may be used in the value and are expanded at runtime.

The following example configures an AddRequestHeader GatewayFilter that uses a variable:

Example 15. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- AddRequestHeader=X-Request-Red, Blue-{segment}

6.2. The AddRequestHeadersIfNotPresent GatewayFilter Factory

The AddRequestHeadersIfNotPresent GatewayFilter factory takes a collection of name and value pairs separated by colon.

The following example configures an AddRequestHeadersIfNotPresent GatewayFilter:

Example 16. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_headers_route

uri: https://example.org

filters:

- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green

This listing adds 2 headers X-Request-Color-1:blue and X-Request-Color-2:green to the downstream request’s headers for all matching requests.

This is similar to how AddRequestHeader works, but unlike AddRequestHeader it will do it only if the header is not already there.

Otherwise, the original value in the client request is sent.

Additionally, to set a multi-valued header, use the header name multiple times like AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-1:green.

AddRequestHeadersIfNotPresent also supports URI variables used to match a path or host.

URI variables may be used in the value and are expanded at runtime.

The following example configures an AddRequestHeadersIfNotPresent GatewayFilter that uses a variable:

Example 17. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- AddRequestHeadersIfNotPresent=X-Request-Red:Blue-{segment}

6.3. The AddRequestParameter GatewayFilter Factory

The AddRequestParameter GatewayFilter Factory takes a name and value parameter.

The following example configures an AddRequestParameter GatewayFilter:

Example 18. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_parameter_route

uri: https://example.org

filters:

- AddRequestParameter=red, blue

This will add red=blue to the downstream request’s query string for all matching requests.

AddRequestParameter is aware of the URI variables used to match a path or host.

URI variables may be used in the value and are expanded at runtime.

The following example configures an AddRequestParameter GatewayFilter that uses a variable:

Example 19. application.yml

spring:

cloud:

gateway:

routes:

- id: add_request_parameter_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- AddRequestParameter=foo, bar-{segment}

6.4. The AddResponseHeader GatewayFilter Factory

The AddResponseHeader GatewayFilter Factory takes a name and value parameter.

The following example configures an AddResponseHeader GatewayFilter:

Example 20. application.yml

spring:

cloud:

gateway:

routes:

- id: add_response_header_route

uri: https://example.org

filters:

- AddResponseHeader=X-Response-Red, Blue

This adds X-Response-Red:Blue header to the downstream response’s headers for all matching requests.

AddResponseHeader is aware of URI variables used to match a path or host.

URI variables may be used in the value and are expanded at runtime.

The following example configures an AddResponseHeader GatewayFilter that uses a variable:

Example 21. application.yml

spring:

cloud:

gateway:

routes:

- id: add_response_header_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- AddResponseHeader=foo, bar-{segment}

6.5. The CircuitBreaker GatewayFilter Factory

The Spring Cloud CircuitBreaker GatewayFilter factory uses the Spring Cloud CircuitBreaker APIs to wrap Gateway routes in

a circuit breaker. Spring Cloud CircuitBreaker supports multiple libraries that can be used with Spring Cloud Gateway. Spring Cloud supports Resilience4J out of the box.

To enable the Spring Cloud CircuitBreaker filter, you need to place spring-cloud-starter-circuitbreaker-reactor-resilience4j on the classpath.

The following example configures a Spring Cloud CircuitBreaker GatewayFilter:

Example 22. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: https://example.org

filters:

- CircuitBreaker=myCircuitBreaker

To configure the circuit breaker, see the configuration for the underlying circuit breaker implementation you are using.

Resilience4J Documentation

The Spring Cloud CircuitBreaker filter can also accept an optional fallbackUri parameter.

Currently, only forward: schemed URIs are supported.

If the fallback is called, the request is forwarded to the controller matched by the URI.

The following example configures such a fallback:

Example 23. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis

- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

The following listing does the same thing in Java:

Example 24. Application.java

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")

.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))

.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")

.build();

}

This example forwards to the /inCaseofFailureUseThis URI when the circuit breaker fallback is called.

Note that this example also demonstrates the (optional) Spring Cloud LoadBalancer load-balancing (defined by the lb prefix on the destination URI).

CircuitBreaker also supports URI variables in the fallbackUri.

This allows more complex routing options, like forwarding sections of the original host or url path using PathPattern expression.

In the example below the call consumingServiceEndpoint/users/1 will be redirected to inCaseOfFailureUseThis/users/1.

Example 25. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint/{*segments}

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis/{segments}

The primary scenario is to use the fallbackUri to define an internal controller or handler within the gateway application.

However, you can also reroute the request to a controller or handler in an external application, as follows:

Example 26. application.yml

spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: CircuitBreaker

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback

In this example, there is no fallback endpoint or handler in the gateway application.

However, there is one in another application, registered under localhost:9994.

In case of the request being forwarded to fallback, the Spring Cloud CircuitBreaker Gateway filter also provides the Throwable that has caused it.

It is added to the ServerWebExchange as the ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR attribute that can be used when handling the fallback within the gateway application.

For the external controller/handler scenario, headers can be added with exception details.

You can find more information on doing so in the FallbackHeaders GatewayFilter Factory section.

6.5.1. Tripping The Circuit Breaker On Status Codes

In some cases you might want to trip a circuit breaker based on the status code

returned from the route it wraps. The circuit breaker config object takes a list of

status codes that if returned will cause the circuit breaker to be tripped. When setting the

status codes you want to trip the circuit breaker you can either use an integer with the status code

value or the String representation of the HttpStatus enumeration.

Example 27. application.yml

spring:

cloud:

gateway:

routes:

- id: circuitbreaker_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingServiceEndpoint

filters:

- name: CircuitBreaker

args:

name: myCircuitBreaker

fallbackUri: forward:/inCaseOfFailureUseThis

statusCodes:

- 500

- "NOT_FOUND"

Example 28. Application.java

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")

.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))

.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")

.build();

}

6.6. The CacheRequestBody GatewayFilter Factory

Some situations necessitate reading the request body. Since the request can be read only once, we need to cache the request body.

You can use the CacheRequestBody filter to cache the request body before sending it downstream and getting the body from exchange attribute.

The following listing shows how to cache the request body GatewayFilter:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("cache_request_body_route", r -> r.path("/downstream/**")

.filters(f -> f.prefixPath("/httpbin")

.cacheRequestBody(String.class).uri(uri))

.build();

}

Example 29. application.yml

spring:

cloud:

gateway:

routes:

- id: cache_request_body_route

uri: lb://downstream

predicates:

- Path=/downstream/**

filters:

- name: CacheRequestBody

args:

bodyClass: java.lang.String

CacheRequestBody extracts the request body and converts it to a body class (such as java.lang.String, defined in the preceding example).

CacheRequestBody then places it in the attributes available from ServerWebExchange.getAttributes(), with a key defined in ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR.

This filter works only with HTTP (including HTTPS) requests.

6.7. The DedupeResponseHeader GatewayFilter Factory

The DedupeResponseHeader GatewayFilter factory takes a name parameter and an optional strategy parameter. name can contain a space-separated list of header names.

The following example configures a DedupeResponseHeader GatewayFilter:

Example 30. application.yml

spring:

cloud:

gateway:

routes:

- id: dedupe_response_header_route

uri: https://example.org

filters:

- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

This removes duplicate values of Access-Control-Allow-Credentials and Access-Control-Allow-Origin response headers in cases when both the gateway CORS logic and the downstream logic add them.

The DedupeResponseHeader filter also accepts an optional strategy parameter.

The accepted values are RETAIN_FIRST (default), RETAIN_LAST, and RETAIN_UNIQUE.

6.8. The FallbackHeaders GatewayFilter Factory

The FallbackHeaders factory lets you add Spring Cloud CircuitBreaker execution exception details in the headers of a request forwarded to a fallbackUri in an external application, as in the following scenario:

Example 31. application.yml

spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: CircuitBreaker

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback

filters:

- name: FallbackHeaders

args:

executionExceptionTypeHeaderName: Test-Header

In this example, after an execution exception occurs while running the circuit breaker, the request is forwarded to the fallback endpoint or handler in an application running on localhost:9994.

The headers with the exception type, message and (if available) root cause exception type and message are added to that request by the FallbackHeaders filter.

You can overwrite the names of the headers in the configuration by setting the values of the following arguments (shown with their default values):

executionExceptionTypeHeaderName ("Execution-Exception-Type")

executionExceptionMessageHeaderName ("Execution-Exception-Message")

rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

For more information on circuit breakers and the gateway see the Spring Cloud CircuitBreaker Factory section.

6.9. The JsonToGrpc GatewayFilter Factory

The JSONToGRPCFilter GatewayFilter Factory converts a JSON payload to a gRPC request.

The filter takes the following arguments:

protoDescriptor: Proto descriptor file.

This file can be generated using protoc and specifying the --descriptor_set_out flag:

protoc --proto_path=src/main/resources/proto/ \

--descriptor_set_out=src/main/resources/proto/hello.pb \

src/main/resources/proto/hello.proto

protoFile: Proto definition file.

service: Short name of the service that handles the request.

method: Method name in the service that handles the request.

streaming is not supported.

application.yml.

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("json-grpc", r -> r.path("/json/hello").filters(f -> {

String protoDescriptor = "file:src/main/proto/hello.pb";

String protoFile = "file:src/main/proto/hello.proto";

String service = "HelloService";

String method = "hello";

return f.jsonToGRPC(protoDescriptor, protoFile, service, method);

}).uri(uri))

spring:

cloud:

gateway:

routes:

- id: json-grpc

uri: https://localhost:6565/testhello

predicates:

- Path=/json/**

filters:

- name: JsonToGrpc

args:

protoDescriptor: file:proto/hello.pb

protoFile: file:proto/hello.proto

service: HelloService

method: hello

When a request is made through the gateway to /json/hello, the request is transformed by using the definition provided in hello.proto, sent to HelloService/hello, and the response back is transformed to JSON.

By default, it creates a NettyChannel by using the default TrustManagerFactory. However, you can customize this TrustManager by creating a bean of type GrpcSslConfigurer:

@Configuration

public class GRPCLocalConfiguration {

@Bean

public GRPCSSLContext sslContext() {

TrustManager trustManager = trustAllCerts();

return new GRPCSSLContext(trustManager);

}

}

6.10. The LocalResponseCache GatewayFilter Factory

This filter allows caching the response body and headers to follow these rules:

It can only cache bodiless GET requests.

It caches the response only for one of the following status codes: HTTP 200 (OK), HTTP 206 (Partial Content), or HTTP 301 (Moved Permanently).

Response data is not cached if Cache-Control header does not allow it (no-store present in the request or no-store or private present in the response).

If the response is already cached and a new request is performed with no-cache value in Cache-Control header, it returns a bodiless response with 304 (Not Modified).

This filter configures the local response cache per route and is available only if the spring.cloud.gateway.filter.local-response-cache.enabled property is enabled. And a local response cache configured globally is also available as feature.

It accepts the first parameter to override the time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours) and a second parameter to set the maximum size of the cache to evict entries for this route (KB, MB, or GB).

The following listing shows how to add local response cache GatewayFilter:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")

.filters(f -> f.prefixPath("/httpbin")

.localResponseCache(Duration.ofMinutes(30), "500MB")

).uri(uri))

.build();

}

or this

application.yaml

spring:

cloud:

gateway:

routes:

- id: resource

uri: http://localhost:9000

predicates:

- Path=/resource

filters:

- LocalResponseCache=30m,500MB

This filter also automatically calculates the max-age value in the HTTP Cache-Control header.

Only if max-age is present on the original response is the value rewritten with the number of seconds set in the timeToLive configuration parameter.

In consecutive calls, this value is recalculated with the number of seconds left until the response expires.

To enable this feature, add com.github.ben-manes.caffeine:caffeine and spring-boot-starter-cache as project dependencies.

If your project creates custom CacheManager beans, it will either need to be marked with @Primary or injected using @Qualifier.

6.11. The MapRequestHeader GatewayFilter Factory

The MapRequestHeader GatewayFilter factory takes fromHeader and toHeader parameters.

It creates a new named header (toHeader), and the value is extracted out of an existing named header (fromHeader) from the incoming http request.

If the input header does not exist, the filter has no impact.

If the new named header already exists, its values are augmented with the new values.

The following example configures a MapRequestHeader:

Example 32. application.yml

spring:

cloud:

gateway:

routes:

- id: map_request_header_route

uri: https://example.org

filters:

- MapRequestHeader=Blue, X-Request-Red

This adds the X-Request-Red: header to the downstream request with updated values from the incoming HTTP request’s Blue header.

6.12. The ModifyRequestBody GatewayFilter Factory

You can use the ModifyRequestBody filter to modify the request body before it is sent downstream by the gateway.

This filter can be configured only by using the Java DSL.

The following listing shows how to modify a request body GatewayFilter:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,

(exchange, s) -> Mono.just(new Hello(s.toUpperCase())))).uri(uri))

.build();

}

static class Hello {

String message;

public Hello() { }

public Hello(String message) {

this.message = message;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

If the request has no body, the RewriteFilter is passed null. Mono.empty() should be returned to assign a missing body in the request.

6.13. The ModifyResponseBody GatewayFilter Factory

You can use the ModifyResponseBody filter to modify the response body before it is sent back to the client.

This filter can be configured only by using the Java DSL.

The following listing shows how to modify a response body GatewayFilter:

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyResponseBody(String.class, String.class,

(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))

.build();

}

If the response has no body, the RewriteFilter is passed null. Mono.empty() should be returned to assign a missing body in the response.

6.14. The PrefixPath GatewayFilter Factory

The PrefixPath GatewayFilter factory takes a single prefix parameter.

The following example configures a PrefixPath GatewayFilter:

Example 33. application.yml

spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: https://example.org

filters:

- PrefixPath=/mypath

This prefixes /mypath to the path of all matching requests.

So a request to /hello is sent to /mypath/hello.

6.15. The PreserveHostHeader GatewayFilter Factory

The PreserveHostHeader GatewayFilter factory has no parameters.

This filter sets a request attribute that the routing filter inspects to determine if the original host header should be sent rather than the host header determined by the HTTP client.

The following example configures a PreserveHostHeader GatewayFilter:

Example 34. application.yml

spring:

cloud:

gateway:

routes:

- id: preserve_host_route

uri: https://example.org

filters:

- PreserveHostHeader

6.16. The RedirectTo GatewayFilter Factory

The RedirectTo GatewayFilter factory takes three parameters, status, url, and optionally includeRequestParams.

The status parameter should be a 300 series redirect HTTP code, such as 301.

The url parameter should be a valid URL.

This is the value of the Location header.

The includeRequestParams parameter indicates whether request query parameters should be included on the url.

When not set, it will be treated as false.

For relative redirects, you should use uri: no://op as the uri of your route definition.

The following listing configures a RedirectTo GatewayFilter:

Example 35. application.yml

spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: https://example.org

filters:

- RedirectTo=302, https://acme.org

This will send a status 302 with a Location:https://acme.org header to perform a redirect.

The following example configures a RedirectTo GatewayFilter with includeRequestParams set to true.

application.yml

spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: https://example.org

filters:

- RedirectTo=302, https://acme.org, true

When a request with query ?skip=10 is made to the gateway, the gateway will send a status 302 with a

Location:https://acme.org?skip=10 header to perform a redirect.

6.17. RemoveJsonAttributesResponseBody GatewayFilter Factory

The RemoveJsonAttributesResponseBody GatewayFilter factory takes a collection of attribute names to search for, an optional last parameter from the list can be a boolean to remove the attributes just at root level (that’s the default value if not present at the end of the parameter configuration, false) or recursively (true).

It provides a convenient method to apply a transformation to JSON body content by deleting attributes from it.

The following example configures an RemoveJsonAttributesResponseBody GatewayFilter:

Example 36. application.yml

spring:

cloud:

gateway:

routes:

- id: removejsonattributes_route

uri: https://example.org

filters:

- RemoveJsonAttributesResponseBody=id,color

This removes attributes "id" and "color" from the JSON content body at root level.

The following example configures an RemoveJsonAttributesResponseBody GatewayFilter that uses the optional last parameter:

Example 37. application.yml

spring:

cloud:

gateway:

routes:

- id: removejsonattributes_recursively_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- RemoveJsonAttributesResponseBody=id,color,true

This removes attributes "id" and "color" from the JSON content body at any level.

6.18. The RemoveRequestHeader GatewayFilter Factory

The RemoveRequestHeader GatewayFilter factory takes a name parameter.

It is the name of the header to be removed.

The following listing configures a RemoveRequestHeader GatewayFilter:

Example 38. application.yml

spring:

cloud:

gateway:

routes:

- id: removerequestheader_route

uri: https://example.org

filters:

- RemoveRequestHeader=X-Request-Foo

This removes the X-Request-Foo header before it is sent downstream.

6.19. The RemoveRequestParameter GatewayFilter Factory

The RemoveRequestParameter GatewayFilter factory takes a name parameter.

It is the name of the query parameter to be removed.

The following example configures a RemoveRequestParameter GatewayFilter:

Example 39. application.yml

spring:

cloud:

gateway:

routes:

- id: removerequestparameter_route

uri: https://example.org

filters:

- RemoveRequestParameter=red

This will remove the red parameter before it is sent downstream.

6.20. The RemoveResponseHeader GatewayFilter Factory

The RemoveResponseHeader GatewayFilter factory takes a name parameter.

It is the name of the header to be removed.

The following listing configures a RemoveResponseHeader GatewayFilter:

Example 40. application.yml

spring:

cloud:

gateway:

routes:

- id: removeresponseheader_route

uri: https://example.org

filters:

- RemoveResponseHeader=X-Response-Foo

This will remove the X-Response-Foo header from the response before it is returned to the gateway client.

To remove any kind of sensitive header, you should configure this filter for any routes for which you may want to do so.

In addition, you can configure this filter once by using spring.cloud.gateway.default-filters and have it applied to all routes.

6.21. The RequestHeaderSize GatewayFilter Factory

The RequestHeaderSize GatewayFilter factory takes maxSize and errorHeaderName parameters.

The maxSize parameter is the maximum data size allowed by the request header (including key and value). The errorHeaderName parameter sets the name of the response header containing an error message, by default it is "errorMessage".

The following listing configures a RequestHeaderSize GatewayFilter:

Example 41. application.yml

spring:

cloud:

gateway:

routes:

- id: requestheadersize_route

uri: https://example.org

filters:

- RequestHeaderSize=1000B

This will send a status 431 if size of any request header is greater than 1000 Bytes.

6.22. The RequestRateLimiter GatewayFilter Factory

The RequestRateLimiter GatewayFilter factory uses a RateLimiter implementation to determine if the current request is allowed to proceed. If it is not, a status of HTTP 429 - Too Many Requests (by default) is returned.

This filter takes an optional keyResolver parameter and parameters specific to the rate limiter (described later in this section).

keyResolver is a bean that implements the KeyResolver interface.

In configuration, reference the bean by name using SpEL.

#{@myKeyResolver} is a SpEL expression that references a bean named myKeyResolver.

The following listing shows the KeyResolver interface:

Example 42. KeyResolver.java

public interface KeyResolver {

Mono resolve(ServerWebExchange exchange);

}

The KeyResolver interface lets pluggable strategies derive the key for limiting requests.

In future milestone releases, there will be some KeyResolver implementations.

The default implementation of KeyResolver is the PrincipalNameKeyResolver, which retrieves the Principal from the ServerWebExchange and calls Principal.getName().

By default, if the KeyResolver does not find a key, requests are denied.

You can adjust this behavior by setting the spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) and spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code properties.

The RequestRateLimiter is not configurable with the "shortcut" notation. The following example below is invalid:

Example 43. application.properties

# INVALID SHORTCUT CONFIGURATION

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

6.22.1. The Redis RateLimiter

The Redis implementation is based on work done at Stripe.

It requires the use of the spring-boot-starter-data-redis-reactive Spring Boot starter.

The algorithm used is the Token Bucket Algorithm.

The redis-rate-limiter.replenishRate property defines how many requests per second to allow (without any dropped requests).

This is the rate at which the token bucket is filled.

The redis-rate-limiter.burstCapacity property is the maximum number of requests a user is allowed in a single second (without any dropped requests).

This is the number of tokens the token bucket can hold.

Setting this value to zero blocks all requests.

The redis-rate-limiter.requestedTokens property is how many tokens a request costs.

This is the number of tokens taken from the bucket for each request and defaults to 1.

A steady rate is accomplished by setting the same value in replenishRate and burstCapacity.

Temporary bursts can be allowed by setting burstCapacity higher than replenishRate.

In this case, the rate limiter needs to be allowed some time between bursts (according to replenishRate), as two consecutive bursts results in dropped requests (HTTP 429 - Too Many Requests).

The following listing configures a redis-rate-limiter:

Rate limits below 1 request/s are accomplished by setting replenishRate to the wanted number of requests, requestedTokens to the timespan in seconds, and burstCapacity to the product of replenishRate and requestedTokens.

For example, setting replenishRate=1, requestedTokens=60, and burstCapacity=60 results in a limit of 1 request/min.

.application.yml

spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: https://example.org

filters:

- name: RequestRateLimiter

args:

redis-rate-limiter.replenishRate: 10

redis-rate-limiter.burstCapacity: 20

redis-rate-limiter.requestedTokens: 1

The following example configures a KeyResolver in Java:

Example 44. Config.java

@Bean

KeyResolver userKeyResolver() {

return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));

}

This defines a request rate limit of 10 per user. A burst of 20 is allowed, but, in the next second, only 10 requests are available.

The KeyResolver is a simple one that gets the user request parameter

NOTE: This is not recommended for production

You can also define a rate limiter as a bean that implements the RateLimiter interface.

In configuration, you can reference the bean by name using SpEL.

#{@myRateLimiter} is a SpEL expression that references a bean with named myRateLimiter.

The following listing defines a rate limiter that uses the KeyResolver defined in the previous listing:

Example 45. application.yml

spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: https://example.org

filters:

- name: RequestRateLimiter

args:

rate-limiter: "#{@myRateLimiter}"

key-resolver: "#{@userKeyResolver}"

6.23. The RewriteLocationResponseHeader GatewayFilter Factory

The RewriteLocationResponseHeader GatewayFilter factory modifies the value of the Location response header, usually to get rid of backend-specific details.

It takes the stripVersionMode, locationHeaderName, hostValue, and protocolsRegex parameters.

The following listing configures a RewriteLocationResponseHeader GatewayFilter:

Example 46. application.yml

spring:

cloud:

gateway:

routes:

- id: rewritelocationresponseheader_route

uri: http://example.org

filters:

- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

For example, for a request of POST api.example.com/some/object/name, the Location response header value of object-service.prod.example.net/v2/some/object/id is rewritten as api.example.com/some/object/id.

The stripVersionMode parameter has the following possible values: NEVER_STRIP, AS_IN_REQUEST (default), and ALWAYS_STRIP.

NEVER_STRIP: The version is not stripped, even if the original request path contains no version.

AS_IN_REQUEST: The version is stripped only if the original request path contains no version.

ALWAYS_STRIP: The version is always stripped, even if the original request path contains version.

The hostValue parameter, if provided, is used to replace the host:port portion of the response Location header.

If it is not provided, the value of the Host request header is used.

The protocolsRegex parameter must be a valid regex String, against which the protocol name is matched.

If it is not matched, the filter does nothing.

The default is http|https|ftp|ftps.

6.24. The RewritePath GatewayFilter Factory

The RewritePath GatewayFilter factory takes a path regexp parameter and a replacement parameter.

This uses Java regular expressions for a flexible way to rewrite the request path.

The following listing configures a RewritePath GatewayFilter:

Example 47. application.yml

spring:

cloud:

gateway:

routes:

- id: rewritepath_route

uri: https://example.org

predicates:

- Path=/red/**

filters:

- RewritePath=/red/?(?.*), /$\{segment}

For a request path of /red/blue, this sets the path to /blue before making the downstream request. Note that the $ should be replaced with $\ because of the YAML specification.

6.25. The RewriteRequestParameter GatewayFilter Factory

The RewriteRequestParameter GatewayFilter factory takes a name parameter and a replacement parameter.

It will rewrite the value of the request parameter of the given name.

If multiple request parameters with the same name are set, they will be replaced with a single value.

If no request parameter is found, no changes will be made.

The following listing configures a RewriteRequestParameter GatewayFilter:

Example 48. application.yml

spring:

cloud:

gateway:

routes:

- id: rewriterequestparameter_route

uri: https://example.org

predicates:

- Path=/products

filters:

- RewriteRequestParameter=campaign,fall2023

For a request to /products?campaign=old, this sets the request parameter to campaign=fall2023.

6.26. The RewriteResponseHeader GatewayFilter Factory

The RewriteResponseHeader GatewayFilter factory takes name, regexp, and replacement parameters.

It uses Java regular expressions for a flexible way to rewrite the response header value.

The following example configures a RewriteResponseHeader GatewayFilter:

Example 49. application.yml

spring:

cloud:

gateway:

routes:

- id: rewriteresponseheader_route

uri: https://example.org

filters:

- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***

For a header value of /42?user=ford&password=omg!what&flag=true, it is set to /42?user=ford&password=***&flag=true after making the downstream request.

You must use $\ to mean $ because of the YAML specification.

6.27. The SaveSession GatewayFilter Factory

The SaveSession GatewayFilter factory forces a WebSession::save operation before forwarding the call downstream.

This is of particular use when using something like Spring Session with a lazy data store, and you need to ensure the session state has been saved before making the forwarded call.

The following example configures a SaveSession GatewayFilter:

Example 50. application.yml

spring:

cloud:

gateway:

routes:

- id: save_session

uri: https://example.org

predicates:

- Path=/foo/**

filters:

- SaveSession

If you integrate Spring Security with Spring Session and want to ensure security details have been forwarded to the remote process, this is critical.

6.28. The SecureHeaders GatewayFilter Factory

The SecureHeaders GatewayFilter factory adds a number of headers to the response, per the recommendation made in this blog post.

The following headers (shown with their default values) are added:

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)

To change the default values, set the appropriate property in the spring.cloud.gateway.filter.secure-headers namespace.

The following properties are available:

xss-protection-header

strict-transport-security

frame-options

content-type-options

referrer-policy

content-security-policy

download-options

permitted-cross-domain-policies

To disable the default values set the spring.cloud.gateway.filter.secure-headers.disable property with comma-separated values.

The following example shows how to do so:

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

The lowercase full name of the secure header needs to be used to disable it..

6.29. The SetPath GatewayFilter Factory

The SetPath GatewayFilter factory takes a path template parameter.

It offers a simple way to manipulate the request path by allowing templated segments of the path.

This uses the URI templates from Spring Framework.

Multiple matching segments are allowed.

The following example configures a SetPath GatewayFilter:

Example 51. application.yml

spring:

cloud:

gateway:

routes:

- id: setpath_route

uri: https://example.org

predicates:

- Path=/red/{segment}

filters:

- SetPath=/{segment}

For a request path of /red/blue, this sets the path to /blue before making the downstream request.

6.30. The SetRequestHeader GatewayFilter Factory

The SetRequestHeader GatewayFilter factory takes name and value parameters.

The following listing configures a SetRequestHeader GatewayFilter:

Example 52. application.yml

spring:

cloud:

gateway:

routes:

- id: setrequestheader_route

uri: https://example.org

filters:

- SetRequestHeader=X-Request-Red, Blue

This GatewayFilter replaces (rather than adding) all headers with the given name.

So, if the downstream server responded with X-Request-Red:1234, it will be replaced with X-Request-Red:Blue, which is what the downstream service would receive.

SetRequestHeader is aware of URI variables used to match a path or host.

URI variables may be used in the value and are expanded at runtime.

The following example configures an SetRequestHeader GatewayFilter that uses a variable:

Example 53. application.yml

spring:

cloud:

gateway:

routes:

- id: setrequestheader_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- SetRequestHeader=foo, bar-{segment}

6.31. The SetResponseHeader GatewayFilter Factory

The SetResponseHeader GatewayFilter factory takes name and value parameters.

The following listing configures a SetResponseHeader GatewayFilter:

Example 54. application.yml

spring:

cloud:

gateway:

routes:

- id: setresponseheader_route

uri: https://example.org

filters:

- SetResponseHeader=X-Response-Red, Blue

This GatewayFilter replaces (rather than adding) all headers with the given name.

So, if the downstream server responded with X-Response-Red:1234, it will be replaced with X-Response-Red:Blue, which is what the gateway client would receive.

SetResponseHeader is aware of URI variables used to match a path or host.

URI variables may be used in the value and will be expanded at runtime.

The following example configures an SetResponseHeader GatewayFilter that uses a variable:

Example 55. application.yml

spring:

cloud:

gateway:

routes:

- id: setresponseheader_route

uri: https://example.org

predicates:

- Host: {segment}.myhost.org

filters:

- SetResponseHeader=foo, bar-{segment}

6.32. The SetStatus GatewayFilter Factory

The SetStatus GatewayFilter factory takes a single parameter, status.

It must be a valid Spring HttpStatus.

It may be the integer value 404 or the string representation of the enumeration: NOT_FOUND.

The following listing configures a SetStatus GatewayFilter:

Example 56. application.yml

spring:

cloud:

gateway:

routes:

- id: setstatusstring_route

uri: https://example.org

filters:

- SetStatus=UNAUTHORIZED

- id: setstatusint_route

uri: https://example.org

filters:

- SetStatus=401

In either case, the HTTP status of the response is set to 401.

You can configure the SetStatus GatewayFilter to return the original HTTP status code from the proxied request in a header in the response.

The header is added to the response if configured with the following property:

Example 57. application.yml

spring:

cloud:

gateway:

set-status:

original-status-header-name: original-http-status

6.33. The StripPrefix GatewayFilter Factory

The StripPrefix GatewayFilter factory takes one parameter, parts.

The parts parameter indicates the number of parts in the path to strip from the request before sending it downstream.

The following listing configures a StripPrefix GatewayFilter:

Example 58. application.yml

spring:

cloud:

gateway:

routes:

- id: nameRoot

uri: https://nameservice

predicates:

- Path=/name/**

filters:

- StripPrefix=2

When a request is made through the gateway to /name/blue/red, the request made to nameservice looks like nameservice/red.

6.34. The Retry GatewayFilter Factory

The Retry GatewayFilter factory supports the following parameters:

retries: The number of retries that should be attempted.

statuses: The HTTP status codes that should be retried, represented by using org.springframework.http.HttpStatus.

methods: The HTTP methods that should be retried, represented by using org.springframework.http.HttpMethod.

series: The series of status codes to be retried, represented by using org.springframework.http.HttpStatus.Series.

exceptions: A list of thrown exceptions that should be retried.

backoff: The configured exponential backoff for the retries.

Retries are performed after a backoff interval of firstBackoff * (factor ^ n), where n is the iteration.

If maxBackoff is configured, the maximum backoff applied is limited to maxBackoff.

If basedOnPreviousValue is true, the backoff is calculated by using prevBackoff * factor.

The following defaults are configured for Retry filter, if enabled:

retries: Three times

series: 5XX series

methods: GET method

exceptions: IOException and TimeoutException

backoff: disabled

The following listing configures a Retry GatewayFilter:

Example 59. application.yml

spring:

cloud:

gateway:

routes:

- id: retry_test

uri: http://localhost:8080/flakey

predicates:

- Host=*.retry.com

filters:

- name: Retry

args:

retries: 3

statuses: BAD_GATEWAY

methods: GET,POST

backoff:

firstBackoff: 10ms

maxBackoff: 50ms

factor: 2

basedOnPreviousValue: false

When using the retry filter with a forward: prefixed URL, the target endpoint should be written carefully so that, in case of an error, it does not do anything that could result in a response being sent to the client and committed.

For example, if the target endpoint is an annotated controller, the target controller method should not return ResponseEntity with an error status code.

Instead, it should throw an Exception or signal an error (for example, through a Mono.error(ex) return value), which the retry filter can be configured to handle by retrying.

When using the retry filter with any HTTP method with a body, the body will be cached and the gateway will become memory constrained. The body is cached in a request attribute defined by ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR. The type of the object is org.springframework.core.io.buffer.DataBuffer.

A simplified "shortcut" notation can be added with a single status and method.

The following two examples are equivalent:

Example 60. application.yml

spring:

cloud:

gateway:

routes:

- id: retry_route

uri: https://example.org

filters:

- name: Retry

args:

retries: 3

statuses: INTERNAL_SERVER_ERROR

methods: GET

backoff:

firstBackoff: 10ms

maxBackoff: 50ms

factor: 2

basedOnPreviousValue: false

- id: retryshortcut_route

uri: https://example.org

filters:

- Retry=3,INTERNAL_SERVER_ERROR,GET,10ms,50ms,2,false

6.35. The RequestSize GatewayFilter Factory

When the request size is greater than the permissible limit, the RequestSize GatewayFilter factory can restrict a request from reaching the downstream service.

The filter takes a maxSize parameter.

The maxSize is a DataSize type, so values can be defined as a number followed by an optional DataUnit suffix such as 'KB' or 'MB'. The default is 'B' for bytes.

It is the permissible size limit of the request defined in bytes.

The following listing configures a RequestSize GatewayFilter:

Example 61. application.yml

spring:

cloud:

gateway:

routes:

- id: request_size_route

uri: http://localhost:8080/upload

predicates:

- Path=/upload

filters:

- name: RequestSize

args:

maxSize: 5000000

The RequestSize GatewayFilter factory sets the response status as 413 Payload Too Large with an additional header errorMessage when the request is rejected due to size. The following example shows such an errorMessage:

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

The default request size is set to five MB if not provided as a filter argument in the route definition.

6.36. The SetRequestHostHeader GatewayFilter Factory

There are certain situation when the host header may need to be overridden. In this situation, the SetRequestHostHeader GatewayFilter factory can replace the existing host header with a specified value.

The filter takes a host parameter.

The following listing configures a SetRequestHostHeader GatewayFilter:

Example 62. application.yml

spring:

cloud:

gateway:

routes:

- id: set_request_host_header_route

uri: http://localhost:8080/headers

predicates:

- Path=/headers

filters:

- name: SetRequestHostHeader

args:

host: example.org

The SetRequestHostHeader GatewayFilter factory replaces the value of the host header with example.org.

6.37. The TokenRelay GatewayFilter Factory

A Token Relay is where an OAuth2 consumer acts as a Client and

forwards the incoming token to outgoing resource requests. The

consumer can be a pure Client (like an SSO application) or a Resource

Server.

Spring Cloud Gateway can forward OAuth2 access tokens downstream to the services

it is proxying. To add this functionality to the gateway, you need to add the TokenRelayGatewayFilterFactory like this:

App.java

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

return builder.routes()

.route("resource", r -> r.path("/resource")

.filters(f -> f.tokenRelay())

.uri("http://localhost:9000"))

.build();

}

or this

application.yaml

spring:

cloud:

gateway:

routes:

- id: resource

uri: http://localhost:9000

predicates:

- Path=/resource

filters:

- TokenRelay=

and it will (in addition to logging the user in and grabbing a token)

pass the authentication token downstream to the services (in this case

/resource).

To enable this for Spring Cloud Gateway add the following dependencies

org.springframework.boot:spring-boot-starter-oauth2-client

How does it work? The

{githubmaster}/src/main/java/org/springframework/cloud/gateway/security/TokenRelayGatewayFilterFactory.java[filter]

extracts an access token from the currently authenticated user,

and puts it in a request header for the downstream requests.

For a full working sample see this project.

A TokenRelayGatewayFilterFactory bean will only be created if the proper spring.security.oauth2.client.* properties are set which will trigger creation of a ReactiveClientRegistrationRepository bean.

The default implementation of ReactiveOAuth2AuthorizedClientService used by TokenRelayGatewayFilterFactory

uses an in-memory data store. You will need to provide your own implementation ReactiveOAuth2AuthorizedClientService

if you need a more robust solution.

6.38. Default Filters

To add a filter and apply it to all routes, you can use spring.cloud.gateway.default-filters.

This property takes a list of filters.

The following listing defines a set of default filters:

Example 63. application.yml

spring:

cloud:

gateway:

default-filters:

- AddResponseHeader=X-Response-Default-Red, Default-Blue

- PrefixPath=/httpbin

7. Global Filters

The GlobalFilter interface has the same signature as GatewayFilter.

These are special filters that are conditionally applied to all routes.

This interface and its usage are subject to change in future milestone releases.

7.1. Combined Global Filter and GatewayFilter Ordering

When a request matches a route, the filtering web handler adds all instances of GlobalFilter and all route-specific instances of GatewayFilter to a filter chain.

This combined filter chain is sorted by the org.springframework.core.Ordered interface, which you can set by implementing the getOrder() method.

As Spring Cloud Gateway distinguishes between “pre” and “post” phases for filter logic execution (see How it Works), the filter with the highest precedence is the first in the “pre”-phase and the last in the “post”-phase.

The following listing configures a filter chain:

Example 64. ExampleConfiguration.java

@Bean

public GlobalFilter customFilter() {

return new CustomGlobalFilter();

}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

log.info("custom global filter");

return chain.filter(exchange);

}

@Override

public int getOrder() {

return -1;

}

}

7.2. The Gateway Metrics Filter

To enable gateway metrics, add spring-boot-starter-actuator as a project dependency. Then, by default, the gateway metrics filter runs as long as the spring.cloud.gateway.metrics.enabled property is not set to false.

This filter adds a timer metric named spring.cloud.gateway.requests with the following tags:

routeId: The route ID.

routeUri: The URI to which the API is routed.

outcome: The outcome, as classified by HttpStatus.Series.

status: The HTTP status of the request returned to the client.

httpStatusCode: The HTTP Status of the request returned to the client.

httpMethod: The HTTP method used for the request.

In addition, through the spring.cloud.gateway.metrics.tags.path.enabled property (by default, false), you can activate an extra metric with the path tag:

path: The path of the request.

These metrics are then available to be scraped from /actuator/metrics/spring.cloud.gateway.requests and can be easily integrated with Prometheus to create a Grafana dashboard.

To enable the prometheus endpoint, add micrometer-registry-prometheus as a project dependency.

7.3. The Local Response Cache Filter

The LocalResponseCache runs if associated properties are enabled:

spring.cloud.gateway.global-filter.local-response-cache.enabled: Activates the global cache for all routes

spring.cloud.gateway.filter.local-response-cache.enabled: Activates the associated filter to use at route level

This feature enables a local cache using Caffeine for all responses that meet the following criteria:

The request is a bodiless GET.

The response has one of the following status codes: HTTP 200 (OK), HTTP 206 (Partial Content), or HTTP 301 (Moved Permanently).

The HTTP Cache-Control header allows caching (that means it does not have any of the following values: no-store present in the request and no-store or private present in the response).

It accepts two configuration parameters:

spring.cloud.gateway.filter.local-response-cache.size: Sets the maximum size of the cache to evict entries for this route (in KB, MB and GB).

spring.cloud.gateway.filter.local-response-cache.time-to-live Sets the time to expire a cache entry (expressed in s for seconds, m for minutes, and h for hours).

If none of these parameters are configured but the global filter is enabled, by default, it configures 5 minutes of time to live for the cached response.

This filter also implements the automatic calculation of the max-age value in the HTTP Cache-Control header.

If max-age is present on the original response, the value is rewritten with the number of seconds set in the timeToLive configuration parameter.

In subsequent calls, this value is recalculated with the number of seconds left until the response expires.

Setting spring.cloud.gateway.global-filter.local-response-cache.enabled to false deactivate the local response cache for all routes, the LocalResponseCache filter allows to use this functionality at route level.

To enable this feature, add com.github.ben-manes.caffeine:caffeine and spring-boot-starter-cache as project dependencies.

If your project creates custom CacheManager beans, it will either need to be marked with @Primary or injected using @Qualifier.

7.4. Forward Routing Filter

The ForwardRoutingFilter looks for a URI in the exchange attribute ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR.

If the URL has a forward scheme (such as forward:///localendpoint), it uses the Spring DispatcherHandler to handle the request.

The path part of the request URL is overridden with the path in the forward URL.

The unmodified original URL is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute.

7.5. The Netty Routing Filter

The Netty routing filter runs if the URL located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a http or https scheme.

It uses the Netty HttpClient to make the downstream proxy request.

The response is put in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute for use in a later filter.

(There is also an experimental WebClientHttpRoutingFilter that performs the same function but does not require Netty.)

7.6. The Netty Write Response Filter

The NettyWriteResponseFilter runs if there is a Netty HttpClientResponse in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute.

It runs after all other filters have completed and writes the proxy response back to the gateway client response.

(There is also an experimental WebClientWriteResponseFilter that performs the same function but does not require Netty.)

7.7. The ReactiveLoadBalancerClientFilter

The ReactiveLoadBalancerClientFilter looks for a URI in the exchange attribute named ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR.

If the URL has a lb scheme (such as lb://myservice), it uses the Spring Cloud ReactorLoadBalancer to resolve the name (myservice in this example) to an actual host and port and replaces the URI in the same attribute.

The unmodified original URL is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute.

The filter also looks in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR attribute to see if it equals lb.

If so, the same rules apply.

The following listing configures a ReactiveLoadBalancerClientFilter:

Example 65. application.yml

spring:

cloud:

gateway:

routes:

- id: myRoute

uri: lb://service

predicates:

- Path=/service/**

By default, when a service instance cannot be found by the ReactorLoadBalancer, a 503 is returned.

You can configure the gateway to return a 404 by setting spring.cloud.gateway.loadbalancer.use404=true.

The isSecure value of the ServiceInstance returned from the ReactiveLoadBalancerClientFilter overrides

the scheme specified in the request made to the Gateway.

For example, if the request comes into the Gateway over HTTPS but the ServiceInstance indicates it is not secure, the downstream request is made over HTTP.

The opposite situation can also apply.

However, if GATEWAY_SCHEME_PREFIX_ATTR is specified for the route in the Gateway configuration, the prefix is stripped and the resulting scheme from the route URL overrides the ServiceInstance configuration.

Gateway supports all the LoadBalancer features. You can read more about them in the Spring Cloud Commons documentation.

7.8. The RouteToRequestUrl Filter

If there is a Route object in the ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange attribute, the RouteToRequestUrlFilter runs.

It creates a new URI, based off of the request URI but updated with the URI attribute of the Route object.

The new URI is placed in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute.

If the URI has a scheme prefix, such as lb:ws://serviceid, the lb scheme is stripped from the URI and placed in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR for use later in the filter chain.

7.9. The Websocket Routing Filter

If the URL located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a ws or wss scheme, the websocket routing filter runs. It uses the Spring WebSocket infrastructure to forward the websocket request downstream.

You can load-balance websockets by prefixing the URI with lb, such as lb:ws://serviceid.

If you use SockJS as a fallback over normal HTTP, you should configure a normal HTTP route as well as the websocket Route.

The following listing configures a websocket routing filter:

Example 66. application.yml

spring:

cloud:

gateway:

routes:

# SockJS route

- id: websocket_sockjs_route

uri: http://localhost:3001

predicates:

- Path=/websocket/info/**

# Normal Websocket route

- id: websocket_route

uri: ws://localhost:3001

predicates:

- Path=/websocket/**

7.10. Marking An Exchange As Routed

After the gateway has routed a ServerWebExchange, it marks that exchange as “routed” by adding gatewayAlreadyRouted

to the exchange attributes. Once a request has been marked as routed, other routing filters will not route the request again,

essentially skipping the filter. There are convenience methods that you can use to mark an exchange as routed

or check if an exchange has already been routed.

ServerWebExchangeUtils.isAlreadyRouted takes a ServerWebExchange object and checks if it has been “routed”.

ServerWebExchangeUtils.setAlreadyRouted takes a ServerWebExchange object and marks it as “routed”.

8. HttpHeadersFilters

HttpHeadersFilters are applied to the requests before sending them downstream, such as in the NettyRoutingFilter.

8.1. Forwarded Headers Filter

The Forwarded Headers Filter creates a Forwarded header to send to the downstream service. It adds the Host header, scheme and port of the current request to any existing Forwarded header.

8.2. RemoveHopByHop Headers Filter

The RemoveHopByHop Headers Filter removes headers from forwarded requests. The default list of headers that is removed comes from the IETF.

The default removed headers are:

Connection

Keep-Alive

Proxy-Authenticate

Proxy-Authorization

TE

Trailer

Transfer-Encoding

Upgrade

To change this, set the spring.cloud.gateway.filter.remove-hop-by-hop.headers property to the list of header names to remove.

8.3. XForwarded Headers Filter

The XForwarded Headers Filter creates various X-Forwarded-* headers to send to the downstream service. It uses the Host header, scheme, port and path of the current request to create the various headers.

Creating of individual headers can be controlled by the following boolean properties (defaults to 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

Appending multiple headers can be controlled by the following boolean properties (defaults to 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

9. TLS and SSL

The gateway can listen for requests on HTTPS by following the usual Spring server configuration.

The following example shows how to do so:

Example 67. application.yml

server:

ssl:

enabled: true

key-alias: scg

key-store-password: scg1234

key-store: classpath:scg-keystore.p12

key-store-type: PKCS12

You can route gateway routes to both HTTP and HTTPS backends.

If you are routing to an HTTPS backend, you can configure the gateway to trust all downstream certificates with the following configuration:

Example 68. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

useInsecureTrustManager: true

Using an insecure trust manager is not suitable for production.

For a production deployment, you can configure the gateway with a set of known certificates that it can trust with the following configuration:

Example 69. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

trustedX509Certificates:

- cert1.pem

- cert2.pem

If the Spring Cloud Gateway is not provisioned with trusted certificates, the default trust store is used (which you can override by setting the javax.net.ssl.trustStore system property).

9.1. TLS Handshake

The gateway maintains a client pool that it uses to route to backends.

When communicating over HTTPS, the client initiates a TLS handshake.

A number of timeouts are associated with this handshake.

You can configure these timeouts can be configured (defaults shown) as follows:

Example 70. application.yml

spring:

cloud:

gateway:

httpclient:

ssl:

handshake-timeout-millis: 10000

close-notify-flush-timeout-millis: 3000

close-notify-read-timeout-millis: 0

10. Configuration

Configuration for Spring Cloud Gateway is driven by a collection of RouteDefinitionLocator instances.

The following listing shows the definition of the RouteDefinitionLocator interface:

Example 71. RouteDefinitionLocator.java

public interface RouteDefinitionLocator {

Flux getRouteDefinitions();

}

By default, a PropertiesRouteDefinitionLocator loads properties by using Spring Boot’s @ConfigurationProperties mechanism.

The earlier configuration examples all use a shortcut notation that uses positional arguments rather than named ones.

The following two examples are equivalent:

Example 72. application.yml

spring:

cloud:

gateway:

routes:

- id: setstatus_route

uri: https://example.org

filters:

- name: SetStatus

args:

status: 401

- id: setstatusshortcut_route

uri: https://example.org

filters:

- SetStatus=401

For some usages of the gateway, properties are adequate, but some production use cases benefit from loading configuration from an external source, such as a database. Future milestone versions will have RouteDefinitionLocator implementations based off of Spring Data Repositories, such as Redis, MongoDB, and Cassandra.

10.1. RouteDefinition Metrics

To enable RouteDefinition metrics, add spring-boot-starter-actuator as a project dependency. Then, by default, the metrics will be available as long as the property spring.cloud.gateway.metrics.enabled is set to true. A gauge metric named spring.cloud.gateway.routes.count will be added, whose value is the number of RouteDefinitions. This metric will be available from /actuator/metrics/spring.cloud.gateway.routes.count.

11. Route Metadata Configuration

You can configure additional parameters for each route by using metadata, as follows:

Example 73. application.yml

spring:

cloud:

gateway:

routes:

- id: route_with_metadata

uri: https://example.org

metadata:

optionName: "OptionValue"

compositeObject:

name: "value"

iAmNumber: 1

You could acquire all metadata properties from an exchange, as follows:

Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);

// get all metadata properties

route.getMetadata();

// get a single metadata property

route.getMetadata(someKey);

12. Http timeouts configuration

Http timeouts (response and connect) can be configured for all routes and overridden for each specific route.

12.1. Global timeouts

To configure Global http timeouts:

connect-timeout must be specified in milliseconds.

response-timeout must be specified as a java.time.Duration

global http timeouts example

spring:

cloud:

gateway:

httpclient:

connect-timeout: 1000

response-timeout: 5s

12.2. Per-route timeouts

To configure per-route timeouts:

connect-timeout must be specified in milliseconds.

response-timeout must be specified in milliseconds.

per-route http timeouts configuration via configuration

- id: per_route_timeouts

uri: https://example.org

predicates:

- name: Path

args:

pattern: /delay/{timeout}

metadata:

response-timeout: 200

connect-timeout: 200

per-route timeouts configuration using Java DSL

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR;

import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR;

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){

return routeBuilder.routes()

.route("test1", r -> {

return r.host("*.somehost.org").and().path("/somepath")

.filters(f -> f.addRequestHeader("header1", "header-value-1"))

.uri("http://someuri")

.metadata(RESPONSE_TIMEOUT_ATTR, 200)

.metadata(CONNECT_TIMEOUT_ATTR, 200);

})

.build();

}

A per-route response-timeout with a negative value will disable the global response-timeout value.

- id: per_route_timeouts

uri: https://example.org

predicates:

- name: Path

args:

pattern: /delay/{timeout}

metadata:

response-timeout: -1

13. Fluent Java Routes API

To allow for simple configuration in Java, the RouteLocatorBuilder bean includes a fluent API.

The following listing shows how it works:

Example 74. GatewaySampleApplication.java

// static imports from GatewayFilters and RoutePredicates

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {

return builder.routes()

.route(r -> r.host("**.abc.org").and().path("/image/png")

.filters(f ->

f.addResponseHeader("X-TestHeader", "foobar"))

.uri("http://httpbin.org:80")

)

.route(r -> r.path("/image/webp")

.filters(f ->

f.addResponseHeader("X-AnotherHeader", "baz"))

.uri("http://httpbin.org:80")

.metadata("key", "value")

)

.route(r -> r.order(-1)

.host("**.throttle.org").and().path("/get")

.filters(f -> f.filter(throttle.apply(1,

1,

10,

TimeUnit.SECONDS)))

.uri("http://httpbin.org:80")

.metadata("key", "value")

)

.build();

}

This style also allows for more custom predicate assertions.

The predicates defined by RouteDefinitionLocator beans are combined using logical and.

By using the fluent Java API, you can use the and(), or(), and negate() operators on the Predicate class.

14. The DiscoveryClient Route Definition Locator

You can configure the gateway to create routes based on services registered with a DiscoveryClient compatible service registry.

To enable this, set spring.cloud.gateway.discovery.locator.enabled=true and make sure a DiscoveryClient implementation (such as Netflix Eureka, Consul, or Zookeeper) is on the classpath and enabled.

14.1. Configuring Predicates and Filters For DiscoveryClient Routes

By default, the gateway defines a single predicate and filter for routes created with a DiscoveryClient.

The default predicate is a path predicate defined with the pattern /serviceId/**, where serviceId is

the ID of the service from the DiscoveryClient.

The default filter is a rewrite path filter with the regex /serviceId/?(?.*) and the replacement /${remaining}.

This strips the service ID from the path before the request is sent downstream.

If you want to customize the predicates or filters used by the DiscoveryClient routes, set spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y].

When doing so, you need to make sure to include the default predicate and filter shown earlier, if you want to retain that functionality.

The following example shows what this looks like:

Example 75. application.properties

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: CircuitBreaker

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 + '/?(?.*)'"

spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

15. Reactor Netty Access Logs

To enable Reactor Netty access logs, set -Dreactor.netty.http.server.accessLogEnabled=true.

It must be a Java System Property, not a Spring Boot property.

You can configure the logging system to have a separate access log file. The following example creates a Logback configuration:

Example 76. logback.xml

access_log.log

%msg%n

16. CORS Configuration

You can configure the gateway to control CORS behavior globally or per route.

Both offer the same possibilities.

16.1. Global CORS Configuration

The “global” CORS configuration is a map of URL patterns to Spring Framework CorsConfiguration.

The following example configures CORS:

Example 77. application.yml

spring:

cloud:

gateway:

globalcors:

cors-configurations:

'[/**]':

allowedOrigins: "https://docs.spring.io"

allowedMethods:

- GET

In the preceding example, CORS requests are allowed from requests that originate from docs.spring.io for all GET requested paths.

To provide the same CORS configuration to requests that are not handled by some gateway route predicate, set the spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping property to true.

This is useful when you try to support CORS preflight requests and your route predicate does not evaluate to true because the HTTP method is options.

16.2. Route CORS Configuration

The “route” configuration allows applying CORS directly to a route as metadata with key cors.

Like in the case of global configuration, the properties belong to Spring Framework CorsConfiguration.

If no Path predicate is present in the route '/**' will be applied.

Example 78. application.yml

spring:

cloud:

gateway:

routes:

- id: cors_route

uri: https://example.org

predicates:

- Path=/service/**

metadata:

cors

allowedOrigins: '*'

allowedMethods:

- GET

- POST

allowedHeaders: '*'

maxAge: 30

17. Actuator API

The /gateway actuator endpoint lets you monitor and interact with a Spring Cloud Gateway application.

To be remotely accessible, the endpoint has to be enabled and exposed over HTTP or JMX in the application properties.

The following listing shows how to do so:

Example 79. application.properties

management.endpoint.gateway.enabled=true # default value

management.endpoints.web.exposure.include=gateway

This endpoint provides an overview of what is available on the child actuator endpoint and the available methods for each reference. The resulting response is similar to the following:

[

{

"href":"/actuator/gateway/",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/routedefinitions",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/globalfilters",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/routefilters",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/routes",

"methods":[ "POST", "GET" ]

},

{

"href":"/actuator/gateway/routepredicates",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/refresh",

"methods":[ "POST" ]

},

{

"href":"/actuator/gateway/routes/route-id-1/combinedfilters",

"methods":[ "GET" ]

},

{

"href":"/actuator/gateway/routes/route-id-1",

"methods":[ "POST", "DELETE", "GET" ]

}

]

17.1. Verbose Actuator Format

A new, more verbose format has been added to Spring Cloud Gateway.

It adds more detail to each route, letting you view the predicates and filters associated with each route along with any configuration that is available.

The following example configures /actuator/gateway/routes:

[

{

"predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",

"route_id": "add_request_header_test",

"filters": [

"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",

"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",

"[[PrefixPath prefix = '/httpbin'], order = 2]"

],

"uri": "lb://testservice",

"order": 0

}

]

This feature is enabled by default. To disable it, set the following property:

Example 80. application.properties

spring.cloud.gateway.actuator.verbose.enabled=false

This will default to true in a future release.

17.2. Retrieving Route Filters

This section details how to retrieve route filters, including:

Global Filters

[gateway-route-filters]

17.2.1. Global Filters

To retrieve the global filters applied to all routes, make a GET request to /actuator/gateway/globalfilters. The resulting response is similar to the following:

{

"org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@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

}

The response contains the details of the global filters that are in place.

For each global filter, there is a string representation of the filter object (for example, org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5) and the corresponding order in the filter chain.

17.2.2. Route Filters

To retrieve the GatewayFilter factories applied to routes, make a GET request to /actuator/gateway/routefilters.

The resulting response is similar to the following:

{

"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,

"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,

"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null

}

The response contains the details of the GatewayFilter factories applied to any particular route.

For each factory there is a string representation of the corresponding object (for example, [SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]).

Note that the null value is due to an incomplete implementation of the endpoint controller, because it tries to set the order of the object in the filter chain, which does not apply to a GatewayFilter factory object.

17.3. Refreshing the Route Cache

To clear the routes cache, make a POST request to /actuator/gateway/refresh.

The request returns a 200 without a response body.

To clear the routes with specific metadata values, add the Query parameter metadata specifying the key:value pairs that the routes to be cleared should match.

If an error is produced during the asynchronous refresh, the refresh will not modify the existing routes.

Sending POST request to /actuator/gateway/refresh?metadata=group:group-1 will only refresh the routes whose group metadata is group-1: first_route and third_route.

[{

"route_id": "first_route",

"route_object": {

"predicate": "...",

},

"metadata": { "group": "group-1" }

},

{

"route_id": "second_route",

"route_object": {

"predicate": "...",

},

"metadata": { "group": "group-2" }

},

{

"route_id": "third_route",

"route_object": {

"predicate": "...",

},

"metadata": { "group": "group-1" }

}]

17.4. Retrieving the Routes Defined in the Gateway

To retrieve the routes defined in the gateway, make a GET request to /actuator/gateway/routes.

The resulting response is similar to the following:

[{

"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

}]

The response contains the details of all the routes defined in the gateway.

The following table describes the structure of each element (each is a route) of the response:

Path

Type

Description

route_id

String

The route ID.

route_object.predicate

Object

The route predicate.

route_object.filters

Array

The GatewayFilter factories applied to the route.

order

Number

The route order.

17.5. Retrieving Information about a Particular Route

To retrieve information about a single route, make a GET request to /actuator/gateway/routes/{id} (for example, /actuator/gateway/routes/first_route).

The resulting response is similar to the following:

{

"id": "first_route",

"predicates": [{

"name": "Path",

"args": {"_genkey_0":"/first"}

}],

"filters": [],

"uri": "https://www.uri-destination.org",

"order": 0

}

The following table describes the structure of the response:

Path

Type

Description

id

String

The route ID.

predicates

Array

The collection of route predicates. Each item defines the name and the arguments of a given predicate.

filters

Array

The collection of filters applied to the route.

uri

String

The destination URI of the route.

order

Number

The route order.

17.6. Creating and Deleting a Particular Route Definition

To create a route definition, make a POST request to /gateway/routes/{id_route_to_create} with a JSON body that specifies the fields of the route (see Retrieving Information about a Particular Route).

To delete a route definition, make a DELETE request to /gateway/routes/{id_route_to_delete}.

17.7. Creating multiple Route Definitions

To create multiple route definitions in a single request, make a POST request to /gateway/routes with a JSON body that specifies the fields of the route, including the route id (see Retrieving Information about a Particular Route).

The route definitions will be discarded if any route raises an error during the creation of the routes.

17.8. Recap: The List of All endpoints

The following table below summarizes the Spring Cloud Gateway actuator endpoints (note that each endpoint has /actuator/gateway as the base-path):

ID

HTTP Method

Description

globalfilters

GET

Displays the list of global filters applied to the routes.

routefilters

GET

Displays the list of GatewayFilter factories applied to a particular route.

refresh

POST

Clears the routes cache.

routes

GET

Displays the list of routes defined in the gateway.

routes/{id}

GET

Displays information about a particular route.

routes/{id}

POST

Adds a new route to the gateway.

routes/{id}

DELETE

Removes an existing route from the gateway.

17.9. Sharing Routes between multiple Gateway instances

Spring Cloud Gateway offers two RouteDefinitionRepository implementations. The first one is the

InMemoryRouteDefinitionRepository which only lives within the memory of one Gateway instance.

This type of Repository is not suited to populate Routes across multiple Gateway instances.

In order to share Routes across a cluster of Spring Cloud Gateway instances, RedisRouteDefinitionRepository can be used.

To enable this kind of repository, the following property has to set to true: spring.cloud.gateway.redis-route-definition-repository.enabled

Likewise to the RedisRateLimiter Filter Factory it requires the use of the spring-boot-starter-data-redis-reactive Spring Boot starter.

18. Troubleshooting

This section covers common problems that may arise when you use Spring Cloud Gateway.

18.1. Log Levels

The following loggers may contain valuable troubleshooting information at the DEBUG and TRACE levels:

org.springframework.cloud.gateway

org.springframework.http.server.reactive

org.springframework.web.reactive

org.springframework.boot.autoconfigure.web

reactor.netty

redisratelimiter

18.2. Wiretap

The Reactor Netty HttpClient and HttpServer can have wiretap enabled.

When combined with setting the reactor.netty log level to DEBUG or TRACE, it enables the logging of information, such as headers and bodies sent and received across the wire.

To enable wiretap, set spring.cloud.gateway.httpserver.wiretap=true or spring.cloud.gateway.httpclient.wiretap=true for the HttpServer and HttpClient, respectively.

19. Developer Guide

These are basic guides to writing some custom components of the gateway.

19.1. Writing Custom Route Predicate Factories

In order to write a Route Predicate you will need to implement RoutePredicateFactory as a bean. There is an abstract class called AbstractRoutePredicateFactory which you can extend.

MyRoutePredicateFactory.java

@Component

public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {

public MyRoutePredicateFactory() {

super(Config.class);

}

@Override

public Predicate apply(Config config) {

// grab configuration from Config object

return exchange -> {

//grab the request

ServerHttpRequest request = exchange.getRequest();

//take information from the request to see if it

//matches configuration.

return matches(config, request);

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

19.2. Writing Custom GatewayFilter Factories

To write a GatewayFilter, you must implement GatewayFilterFactory as a bean.

You can extend an abstract class called AbstractGatewayFilterFactory.

The following examples show how to do so:

Example 81. PreGatewayFilterFactory.java

@Component

public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PreGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

//If you want to build a "pre" filter you need to manipulate the

//request before calling chain.filter

ServerHttpRequest.Builder builder = exchange.getRequest().mutate();

//use builder to manipulate the request

return chain.filter(exchange.mutate().request(builder.build()).build());

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

PostGatewayFilterFactory.java

@Component

public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PostGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

ServerHttpResponse response = exchange.getResponse();

//Manipulate the response in some way

}));

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}

19.2.1. Naming Custom Filters And References In Configuration

Custom filters class names should end in GatewayFilterFactory.

For example, to reference a filter named Something in configuration files, the filter

must be in a class named SomethingGatewayFilterFactory.

It is possible to create a gateway filter named without the

GatewayFilterFactory suffix, such as class AnotherThing. This filter could be

referenced as AnotherThing in configuration files. This is not a supported naming

convention and this syntax may be removed in future releases. Please update the filter

name to be compliant.

19.3. Writing Custom Global Filters

To write a custom global filter, you must implement GlobalFilter interface as a bean.

This applies the filter to all requests.

The following examples show how to set up global pre- and post-filters, respectively:

@Bean

public GlobalFilter customGlobalFilter() {

return (exchange, chain) -> exchange.getPrincipal()

.map(Principal::getName)

.defaultIfEmpty("Default User")

.map(userName -> {

//adds header to proxied request

exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();

return exchange;

})

.flatMap(chain::filter);

}

@Bean

public GlobalFilter customGlobalPostFilter() {

return (exchange, chain) -> chain.filter(exchange)

.then(Mono.just(exchange))

.map(serverWebExchange -> {

//adds header to response

serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",

HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");

return serverWebExchange;

})

.then();

}

20. Building a Simple Gateway by Using Spring MVC or Webflux

The following describes an alternative style gateway. None of the prior documentation applies to what follows.

Spring Cloud Gateway provides a utility object called ProxyExchange.

You can use it inside a regular Spring web handler as a method parameter.

It supports basic downstream HTTP exchanges through methods that mirror the HTTP verbs.

With MVC, it also supports forwarding to a local handler through the forward() method.

To use the ProxyExchange, include the right module in your classpath (either spring-cloud-gateway-mvc or spring-cloud-gateway-webflux).

The following MVC example proxies a request to /test downstream to a remote server:

@RestController

@SpringBootApplication

public class GatewaySampleApplication {

@Value("${remote.home}")

private URI home;

@GetMapping("/test")

public ResponseEntity proxy(ProxyExchange proxy) throws Exception {

return proxy.uri(home.toString() + "/image/png").get();

}

}

The following example does the same thing with Webflux:

@RestController

@SpringBootApplication

public class GatewaySampleApplication {

@Value("${remote.home}")

private URI home;

@GetMapping("/test")

public Mono> proxy(ProxyExchange proxy) throws Exception {

return proxy.uri(home.toString() + "/image/png").get();

}

}

Convenience methods on the ProxyExchange enable the handler method to discover and enhance the URI path of the incoming request.

For example, you might want to extract the trailing elements of a path to pass them downstream:

@GetMapping("/proxy/path/**")

public ResponseEntity proxyPath(ProxyExchange proxy) throws Exception {

String path = proxy.path("/proxy/path/");

return proxy.uri(home.toString() + "/foos/" + path).get();

}

All the features of Spring MVC and Webflux are available to gateway handler methods.

As a result, you can inject request headers and query parameters, for instance, and you can constrain the incoming requests with declarations in the mapping annotation.

See the documentation for @RequestMapping in Spring MVC for more details of those features.

You can add headers to the downstream response by using the header() methods on ProxyExchange.

You can also manipulate response headers (and anything else you like in the response) by adding a mapper to the get() method (and other methods).

The mapper is a Function that takes the incoming ResponseEntity and converts it to an outgoing one.

First-class support is provided for “sensitive” headers (by default, cookie and authorization), which are not passed downstream, and for “proxy” (x-forwarded-*) headers.

21. AOT and Native Image Support

Since 4.0.0, Spring Cloud Gateway supports Spring AOT transformations and native images.

If you’re using load-balanced routes, you need to explicitly define your LoadBalancerClient service IDs. You can do so by using the value or name attributes of the @LoadBalancerClient annotation or as values of the spring.cloud.loadbalancer.eager-load.clients property.

22. Configuration properties

To see the list of all Spring Cloud Gateway related configuration properties, see the appendix.

微服务网关:SpringCloud Gateway保姆级入门教程 - 知乎

微服务网关:SpringCloud Gateway保姆级入门教程 - 知乎切换模式写文章登录/注册微服务网关:SpringCloud Gateway保姆级入门教程授人以渔Java领域;架构知识;面试心得;互联网行业最新资讯什么是微服务网关SpringCloud Gateway是Spring全家桶中一个比较新的项目,Spring社区是这么介绍它的:该项目借助Spring WebFlux的能力,打造了一个API网关。旨在提供一种简单而有效的方法来作为API服务的路由,并为它们提供各种增强功能,例如:安全性,监控和可伸缩性。而在真实的业务领域,我们经常用SpringCloud Gateway来做微服务网关,如果你不理解微服务网关和传统网关的区别,可以阅读此篇文章 Service Mesh和API Gateway关系深度探讨 来了解两者的定位区别。以我粗浅的理解,传统的API网关,往往是独立于各个后端服务,请求先打到独立的网关层,再打到服务集群。而微服务网关,将流量从南北走向改为东西走向(见下图), 微服务网关和后端服务是在同一个容器中的 ,所以也有个别名,叫做Gateway Sidecar。为啥叫Sidecar,这个词应该怎么理解呢,吃鸡里的三蹦子见过没:摩托车是你的后端服务,而旁边挂着的额外座椅就是微服务网关,它是依附于后端服务的(一般是指两个进程在同一个容器中),是不是生动形象了一些。由于本人才疏学浅,对于微服务相关概念理解上难免会有偏差。就不在此详细讲述原理性的文字了。本文只探讨SpringCloud Gateway的入门搭建和实战踩坑。如果小伙伴们对原理感兴趣,可以等后续原理分析文章。注:本文网关项目在笔者公司已经上线运行,每天承担百万级别的请求,是经过实战验证的项目。文章目录手把手造一个网关引入pom依赖编写yml文件接口转义问题获取请求体(Request Body)踩坑实战获取客户端真实IP尾缀匹配总结源代码完整项目源代码已经收录到我的Github:https://github.com/qqxx6661/springcloud_gateway_demo手把手造一个网关引入pom依赖我使用了spring-boot 2.2.5.RELEASE作为parent依赖:

org.springframework.boot

spring-boot-starter-parent

2.2.5.RELEASE

在dependencyManagement中, 我们需要指定sringcloud的版本 ,以便保证我们能够引入我们想要的SpringCloud Gateway版本,所以需要用到dependencyManagement:

org.springframework.cloud

spring-cloud-dependencies

Hoxton.SR8

pom

import

最后,是在dependency中引入spring-cloud-starter-gateway:

org.springframework.cloud

spring-cloud-starter-gateway

如此一来,我们便引入了2.2.5.RELEASE版本的网关:此外,请检查一下你的依赖中是否含有spring-boot-starter-web,如果有, 请干掉它 。因为我们的SpringCloud Gateway是一个netty+webflux实现的web服务器,和Springboot Web本身就是冲突的。

org.springframework.boot

spring-boot-starter-web

做到这里,实际上你的项目就已经可以启动了,运行SpringcloudGatewayApplication,得到结果如图:编写yml文件SpringBoot的核心概念是 约定优先于配置 ,在以前初学Spring时,一直不理解这句话的意思,在使用SpringCloud Gateway时,更加深入的理解了这句话。在默认情况下,你不需要任何的配置,就能够运行起来最基本的网关。针对你之后特定的需求,再去追加配置。而SpringCloud Gateway更强大的一点就是内置了非常多的默认功能实现, 你需要的大部分功能,比如在请求中添加一个header,添加一个参数,都只需要在yml中引入相应的内置过滤器即可。可以说,yml是整个SpringCloud Gateway的灵魂。一个网关最基本的功能,就是配置路由,在这方面,SpringCloud Gateway支持非常多方式。比如:通过时间匹配通过 Cookie 匹配通过 Header 属性匹配通过 Host 匹配通过请求方式匹配通过请求路径匹配通过请求参数匹配通过请求 ip 地址进行匹配这些在官网教程中,都有详细的介绍,就算你百度下,也会有很多民间翻译的入门教程,我就不再赘述了,我只用一个请求路径做一个简单的例子。在公司的项目中,由于有新老两套后台服务,我们使用不同的uri路径进行区分。老服务路径为:url/api/xxxxxx,服务端口号为8001新服务路径为:url/api/v2/xxxxx,服务端口号为8002那么可以直接在yml里面配置:logging:

level:

org.springframework.cloud.gateway: DEBUG

reactor.netty.http.client: DEBUG

spring:

cloud:

gateway:

default-filters:

- AddRequestHeader=gateway-env, springcloud-gateway

routes:

- id: "server_v2"

uri: "http://127.0.0.1:8002"

predicates:

- Path=/api/v2/**

- id: "server_v1"

uri: "http://127.0.0.1:8001"

predicates:

- Path=/api/**上面的代码解释如下:logging:由于文章需要,我们打开gateway和netty的Debug模式,可以看清楚请求进来后执行的流程,方便后续说明。default-filters:我们可以方便的使用default-filters,在请求中加入一个自定义的header,我们加入一个KV为gateway-env:springcloud-gateway,来注明我们这个请求经过了此网关。这样做的好处是后续服务端也能够看到。routes:路由是网关的重点,相信读者们看代码也能理解,我配置了两个路由,一个是server_v1的老服务,一个是server_v2的新服务。 请注意,一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发。 由于我们老服务的路由是/xx,所以需要将老服务放在后面,优先匹配词缀/v2的新服务,不满足的再匹配到/xx。来看一下http://localhost:8080/api/xxxxx的结果:来看一下http://localhost:8080/api/v2/xxxxx的结果:可以看到两个请求被正确的路由了。由于我们真正并没有开启后端服务,所以最后一句error请忽略。接口转义问题在公司实际的项目中,我在搭建好网关后,遇到了一个接口转义问题,相信很多读者可能也会碰到,所以在这里我们最好是防患于未然,优先处理下。问题是这样的,很多老项目在url上并没有进行转义,导致会出现如下接口请求, http://xxxxxxxxx/api/b3d56a6fa19975ba520189f3f55de7f6/140x140.jpg?t=1 "这样请求过来,网关会报错:java.lang.IllegalArgumentException: Invalid character '=' for QUERY_PARAM in "http://pic1.ajkimg.com/display/anjuke/b3d56a6fa19975ba520189f3f55de7f6/140x140.jpg?t=1"在不修改服务代码逻辑的前提下,网关其实已经可以解决这件事情,解决办法就是升级到2.1.1.RELEASE以上的版本。The issue was fixed in version spring-cloud-gateway 2.1.1.RELEASE.所以我们一开始就是用了高版本2.2.5.RELEASE,避免了这个问题,如果小伙伴发现之前使用的版本低于 2.1.1.RELEASE,请升级。获取请求体(Request Body)在网关的使用中,有时候会需要拿到请求body里面的数据,比如验证签名,body可能需要参与签名校验。但是SpringCloud Gateway由于底层采用了webflux,其请求是流式响应的,即 Reactor 编程,要读取 Request Body 中的请求参数就没那么容易了。网上谷歌了很久,很多解决方案要么是彻底过时,要么是版本不兼容,好在最后参考了这篇文章,终于有了思路:https://www.jianshu.com/p/db3b15aec646首先我们需要将body从请求中拿出来,由于是流式处理,Request的Body是只能读取一次的,如果直接通过在Filter中读取,会导致后面的服务无法读取数据。SpringCloud Gateway 内部提供了一个断言工厂类ReadBodyPredicateFactory,这个类实现了读取Request的Body内容并放入缓存,我们可以通过从缓存中获取body内容来实现我们的目的。首先新建一个CustomReadBodyRoutePredicateFactory类,这里只贴出关键代码,完整代码请看可运行的 Github仓库 :@Component

public class CustomReadBodyRoutePredicateFactory extends AbstractRoutePredicateFactory {

protected static final Log log = LogFactory.getLog(CustomReadBodyRoutePredicateFactory.class);

private List> messageReaders;

@Value("${spring.codec.max-in-memory-size}")

private DataSize maxInMemory;

public CustomReadBodyRoutePredicateFactory() {

super(Config.class);

this.messageReaders = HandlerStrategies.withDefaults().messageReaders();

}

public CustomReadBodyRoutePredicateFactory(List> messageReaders) {

super(Config.class);

this.messageReaders = messageReaders;

}

@PostConstruct

private void overrideMsgReaders() {

this.messageReaders = HandlerStrategies.builder().codecs((c) -> c.defaultCodecs().maxInMemorySize((int) maxInMemory.toBytes())).build().messageReaders();

}

@Override

public AsyncPredicate applyAsync(Config config) {

return new AsyncPredicate() {

@Override

public Publisher apply(ServerWebExchange exchange) {

Class inClass = config.getInClass();

Object cachedBody = exchange.getAttribute("cachedRequestBodyObject");

if (cachedBody != null) {

try {

boolean test = config.predicate.test(cachedBody);

exchange.getAttributes().put("read_body_predicate_test_attribute", test);

return Mono.just(test);

} catch (ClassCastException var6) {

if (CustomReadBodyRoutePredicateFactory.log.isDebugEnabled()) {

CustomReadBodyRoutePredicateFactory.log.debug("Predicate test failed because class in predicate does not match the cached body object", var6);

}

return Mono.just(false);

}

} else {

return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {

return ServerRequest.create(exchange.mutate().request(serverHttpRequest).build(), CustomReadBodyRoutePredicateFactory.this.messageReaders).bodyToMono(inClass).doOnNext((objectValue) -> {

exchange.getAttributes().put("cachedRequestBodyObject", objectValue);

}).map((objectValue) -> {

return config.getPredicate().test(objectValue);

}).thenReturn(true);

});

}

}

@Override

public String toString() {

return String.format("ReadBody: %s", config.getInClass());

}

};

}

@Override

public Predicate apply(Config config) {

throw new UnsupportedOperationException("ReadBodyPredicateFactory is only async.");

}

}代码主要作用:在有body的请求到来时,将body读取出来放到内存缓存中。若没有body,则不作任何操作。这样我们便可以在拦截器里使用exchange.getAttribute("cachedRequestBodyObject")得到body体。对了,我们还没有演示一个filter是如何写的,在这里就先写一个完整的demofilter。让我们新建类DemoGatewayFilterFactory:@Component

public class DemoGatewayFilterFactory extends AbstractGatewayFilterFactory {

private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";

public DemoGatewayFilterFactory() {

super(Config.class);

log.info("Loaded GatewayFilterFactory [DemoFilter]");

}

@Override

public List shortcutFieldOrder() {

return Collections.singletonList("enabled");

}

@Override

public GatewayFilter apply(DemoGatewayFilterFactory.Config config) {

return (exchange, chain) -> {

if (!config.isEnabled()) {

return chain.filter(exchange);

}

log.info("-----DemoGatewayFilterFactory start-----");

ServerHttpRequest request = exchange.getRequest();

log.info("RemoteAddress: [{}]", request.getRemoteAddress());

log.info("Path: [{}]", request.getURI().getPath());

log.info("Method: [{}]", request.getMethod());

log.info("Body: [{}]", (String) exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY));

log.info("-----DemoGatewayFilterFactory end-----");

return chain.filter(exchange);

};

}

public static class Config {

private boolean enabled;

public Config() {}

public boolean isEnabled() {

return enabled;

}

public void setEnabled(boolean enabled) {

this.enabled = enabled;

}

}

}这个filter里,我们拿到了新鲜的请求,并且打印出了他的path,method,body等。我们发送一个post请求,body就写一个“我是body”,运行网关,得到结果:是不是非常清晰明了!你以为这就结束了吗?这里有两个非常大的坑。1. body为空时处理上面贴出的CustomReadBodyRoutePredicateFactory类其实已经是我修复过的代码,里面有一行 .thenReturn(true) 是需要加上的。这才能保证当body为空时,不会报出异常。至于为啥一开始写的有问题,显然因为我偷懒了,直接copy网上的代码了,哈哈哈哈哈。2. body大小超过了buffer的最大限制这个情况是在公司项目上线后才发现的,我们的请求里body有时候会比较大,但是网关会有默认大小限制。所以上线后发现了频繁的报错:org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer : 262144谷歌后,找到了解决方案,需要在配置中增加了如下配置spring:

codec:

max-in-memory-size: 5MB把buffer大小改到了5M。你以为这就又双叕结束了,太天真了,你会发现可能没有生效。问题的根源在这里:我们在spring配置了上面的参数,但是我们自定义的拦截器是会初始化ServerRequest, 这个DefaultServerRequest中的HttpMessageReader会使用默认的262144所以我们在此处需要从Spring中取出CodecConfigurer, 并将里面的Reader传给serverRequest。详细的debug过程可以看这篇参考文献:http://theclouds.io/tag/spring-gateway/OK,找到问题后,就可以修改我们的代码,在CustomReadBodyRoutePredicateFactory里,增加:@Value("${spring.codec.max-in-memory-size}")

private DataSize maxInMemory;

@PostConstruct

private void overrideMsgReaders() {

this.messageReaders = HandlerStrategies.builder().codecs((c) -> c.defaultCodecs().maxInMemorySize((int) maxInMemory.toBytes())).build().messageReaders();

}这样每次就会使用我们的5MB来作为最大缓存限制了。依然提醒一下,完整的代码可以请看可运行的 Github仓库讲到这里,入门实战就差不多了,你的网关已经可以上线使用了,你要做的就是加上你需要的业务功能,比如日志,延签,统计等。踩坑实战获取客户端真实IP很多时候,我们的后端服务会去通过host拿到用户的真实IP,但是通过外层反向代理nginx的转发,很可能就需要从header里拿X-Forward-XXX类似这样的参数,才能拿到真实IP。在我们加入了微服务网关后,这个复杂的链路中又增加了一环。这不,如果你不做任何设置,由于你的网关和后端服务在同一个容器中,你的后端服务很有可能就会拿到localhost:8080(你的网关端口)这样的IP。这时候,你需要在yml里配置PreserveHostHeader,这是SpringCloud Gateway自带的实现:filters:

- PreserveHostHeader # 防止host被修改为localhost字面意思, 就是将Host的Header保留起来,透传给后端服务。filter里面的源码贴出来给大家:public GatewayFilter apply(Object config) {

return new GatewayFilter() {

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

exchange.getAttributes().put(ServerWebExchangeUtils.PRESERVE_HOST_HEADER_ATTRIBUTE, true);

return chain.filter(exchange);

}

public String toString() {

return GatewayToStringStyler.filterToStringCreator(PreserveHostHeaderGatewayFilterFactory.this).toString();

}

};

}尾缀匹配公司的项目中,老的后端仓库api都以.json结尾 (/api/xxxxxx.json) ,这就催生了一个需求,当我们对老接口进行了重构后,希望其打到我们的新服务,我们就要将.json这个尾缀切除。可以在filters里设置:filters:

- RewritePath=(?/?.*).json, $\{segment} # 重构接口抹去.json尾缀这样就可以实现打到后端的接口去除了.json后缀。总结本文带领读者一步步完成了一个微服务网关的搭建,并且将许多可能隐藏的坑进行了解决。最后的成品项目在笔者公司已经上线运行,并且增加了签名验证,日志记录等业务,每天承担百万级别的请求,是经过实战验证过的项目。最后再发一次项目源码仓库:https://github.com/qqxx6661/springcloud_gateway_demo感谢大家的支持,如果文章对你起到了一丁点帮助,请点赞转发支持一下!原文链接:http://www.cnblogs.com/rude3knife/p/springcloud_gateway.html如果觉得本文对你有帮助,可以点进主页一起学习进步发布于 2021-06-11 17:36网关API 网关Spring​赞同 39​​1 条评论​分享​喜欢​收藏​申请

Spring Cloud Gateway 2.1.0 中文官网文档-腾讯云开发者社区-腾讯云

ng Cloud Gateway 2.1.0 中文官网文档-腾讯云开发者社区-腾讯云高广超Spring Cloud Gateway 2.1.0 中文官网文档关注作者腾讯云开发者社区文档建议反馈控制台首页学习活动专区工具TVP最新优惠活动文章/答案/技术大牛搜索搜索关闭发布登录/注册首页学习活动专区工具TVP最新优惠活动返回腾讯云官网高广超首页学习活动专区工具TVP最新优惠活动返回腾讯云官网社区首页 >专栏 >Spring Cloud Gateway 2.1.0 中文官网文档Spring Cloud Gateway 2.1.0 中文官网文档高广超关注发布于 2019-03-15 15:35:4758.2K1发布于 2019-03-15 15:35:47举报文章被收录于专栏:互联网技术栈互联网技术栈目录1. How to Include Spring Cloud Gateway

2. Glossary

3. How It Works

4. Route Predicate Factories

5. GatewayFilter Factories

6. Global Filters

7. TLS / SSL

8. Configuration

9. Reactor Netty Access Logs

10. CORS Configuration

11. Actuator API

12. Developer Guide复制该项目提供了一个建立在Spring Ecosystem之上的API网关,包括:Spring 5,Spring Boot 2和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方式来对API进行路由,并为他们提供切面,例如:安全性,监控/指标 和弹性等。1. 如何在工程中引用Spring Cloud Gateway要在项目中引入Spring Cloud Gateway,需要引用 group org.springframework.cloud 和 artifact id为spring-cloud-starter-gateway starter。最新的Spring Cloud Release 构建信息,请参阅Spring Cloud Project page。如果应用了该starter,但由于某种原因不希望启用网关,请进行设置spring.cloud.gateway.enabled=false。 重要

Spring Cloud Gateway依赖Spring Boot和Spring Webflux提供的Netty runtime。它不能在传统的Servlet容器中工作或构建为WAR

2. 词汇表 Route 路由:gateway的基本构建模块。它由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。 Predicate 断言:这是一个Java 8 Function Predicate。输入类型是 Spring Framework ServerWebExchange。这允许开发人员可以匹配来自HTTP请求的任何内容,例如Header或参数。 Filter 过滤器:这些是使用特定工厂构建的 Spring FrameworkGatewayFilter实例。所以可以在返回请求之前或之后修改请求和响应的内容。3. 如何工作的Spring Cloud Gateway Diagram客户端向Spring Cloud Gateway发出请求。如果Gateway Handler Mapping确定请求与路由匹配,则将其发送到Gateway Web Handler。此handler通过特定于该请求的过滤器链处理请求。图中filters被虚线划分的原因是filters可以在发送代理请求之前或之后执行逻辑。先执行所有“pre filter”逻辑,然后进行请求代理。在请求代理执行完后,执行“post filter”逻辑。 注意

HTTP和HTTPS URI默认端口设置是80和443。

4. 路由断言FactoriesSpring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础结构的一部分进行匹配。Spring Cloud Gateway包含许多内置的路由断言Factories。这些断言都匹配HTTP请求的不同属性。多个路由断言Factories可以通过 and 组合使用。4.1 After 路由断言 FactoryAfter Route Predicate Factory采用一个参数——日期时间。在该日期时间之后发生的请求都将被匹配。application.ymlspring:

cloud:

gateway:

routes:

- id: after_route

uri: http://example.org

predicates:

- After=2017-01-20T17:42:47.789-07:00[America/Denver]复制4.2 Before 路由断言 FactoryBefore Route Predicate Factory采用一个参数——日期时间。在该日期时间之前发生的请求都将被匹配。application.yml.spring:

cloud:

gateway:

routes:

- id: before_route

uri: http://example.org

predicates:

- Before=2017-01-20T17:42:47.789-07:00[America/Denver]复制4.3 Between 路由断言 FactoryBetween 路由断言 Factory有两个参数,datetime1和datetime2。在datetime1和datetime2之间的请求将被匹配。datetime2参数的实际时间必须在datetime1之后。application.yml.spring:

cloud:

gateway:

routes:

- id: between_route

uri: http://example.org

predicates:

- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]复制4.4 Cookie 路由断言 FactoryCookie 路由断言 Factory有两个参数,cookie名称和正则表达式。请求包含次cookie名称且正则表达式为真的将会被匹配。application.ymlspring:

cloud:

gateway:

routes:

- id: cookie_route

uri: http://example.org

predicates:

- Cookie=chocolate, ch.p复制4.5 Header 路由断言 FactoryHeader 路由断言 Factory有两个参数,header名称和正则表达式。请求包含次header名称且正则表达式为真的将会被匹配。application.yml.spring:

cloud:

gateway:

routes:

- id: header_route

uri: http://example.org

predicates:

- Header=X-Request-Id, \d+复制4.6 Host 路由断言 FactoryHost 路由断言 Factory包括一个参数:host name列表。使用Ant路径匹配规则,.作为分隔符。

application.yml.spring:

cloud:

gateway:

routes:

- id: host_route

uri: http://example.org

predicates:

- Host=**.somehost.org,**.anotherhost.org复制4.7 Method 路由断言 FactoryMethod 路由断言 Factory只包含一个参数: 需要匹配的HTTP请求方式application.yml.spring:

cloud:

gateway:

routes:

- id: method_route

uri: http://example.org

predicates:

- Method=GET复制所有GET请求都将被路由4.8 Path 路由断言 FactoryPath 路由断言 Factory 有2个参数: 一个Spring PathMatcher表达式列表和可选matchOptionalTrailingSeparator标识 .application.yml.spring:

cloud:

gateway:

routes:

- id: host_route

uri: http://example.org

predicates:

- Path=/foo/{segment},/bar/{segment}复制例如: /foo/1 or /foo/bar or /bar/baz的请求都将被匹配URI 模板变量 (如上例中的 segment ) 将以Map的方式保存于ServerWebExchange.getAttributes() key为ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE. 这些值将在GatewayFilter Factories使用可以使用以下方法来更方便地访问这些变量。Map uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);

String segment = uriVariables.get("segment");复制4.9 Query 路由断言 FactoryQuery 路由断言 Factory 有2个参数: 必选项 param 和可选项 regexp.application.yml.spring:

cloud:

gateway:

routes:

- id: query_route

uri: http://example.org

predicates:

- Query=baz复制则包含了请求参数 baz的都将被匹配。application.yml.spring:

cloud:

gateway:

routes:

- id: query_route

uri: http://example.org

predicates:

- Query=foo, ba.复制如果请求参数里包含foo参数,并且值匹配为ba. 表达式,则将会被路由,如:bar and baz4.10 RemoteAddr 路由断言 FactoryRemoteAddr 路由断言 Factory的参数为 一个CIDR符号(IPv4或IPv6)字符串的列表,最小值为1,例如192.168.0.1/16(其中192.168.0.1是IP地址并且16是子网掩码)。application.yml.spring:

cloud:

gateway:

routes:

- id: remoteaddr_route

uri: http://example.org

predicates:

- RemoteAddr=192.168.1.1/24复制如果请求的remote address 为 192.168.1.10则将被路由4.10.1 修改远程地址的解析方式默认情况下,RemoteAddr 路由断言 Factory使用传入请求中的remote address。如果Spring Cloud Gateway位于代理层后面,则可能与实际客户端IP地址不匹配。可以通过设置自定义RemoteAddressResolver来自定义解析远程地址的方式。Spring Cloud Gateway网关附带一个非默认远程地址解析程序,它基于X-Forwarded-For header, XForwardedRemoteAddressResolver.XForwardedRemoteAddressResolver 有两个静态构造函数方法,采用不同的安全方法:XForwardedRemoteAddressResolver::TrustAll返回一个RemoteAddressResolver,它始终采用X-Forwarded-for头中找到的第一个IP地址。这种方法容易受到欺骗,因为恶意客户端可能会为解析程序接受的“x-forwarded-for”设置初始值。XForwardedRemoteAddressResolver::MaxTrustedIndex获取一个索引,该索引与在Spring Cloud网关前运行的受信任基础设施数量相关。例如,如果SpringCloudGateway只能通过haproxy访问,则应使用值1。如果在访问Spring Cloud Gateway之前需要两个受信任的基础架构跃点,那么应该使用2。给定以下的header值:X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3复制下面的` maxTrustedIndex值将生成以下远程地址:image.pngJava 配置方式:GatewayConfig.javaRemoteAddressResolver resolver = XForwardedRemoteAddressResolver

.maxTrustedIndex(1);

...

.route("direct-route",

r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")

.uri("https://downstream1")

.route("proxied-route",

r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")

.uri("https://downstream2")

)复制5. GatewayFilter Factories过滤器允许以某种方式修改传入的HTTP请求或返回的HTTP响应。过滤器的作用域是某些特定路由。Spring Cloud Gateway包括许多内置的 Filter工厂。注意:有关如何使用以下任何过滤器的更详细示例,请查看unit tests.。5.1 AddRequestHeader GatewayFilter Factory采用一对名称和值作为参数

application.yml.spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: http://example.org

filters:

- AddRequestHeader=X-Request-Foo, Bar复制对于所有匹配的请求,这将向下游请求的头中添加 x-request-foo:bar header5.2 AddRequestParameter GatewayFilter Factory采用一对名称和值作为参数

application.yml.spring:

cloud:

gateway:

routes:

- id: add_request_parameter_route

uri: http://example.org

filters:

- AddRequestParameter=foo, bar复制对于所有匹配的请求,这将向下游请求添加foo=bar查询字符串5.3 AddResponseHeader GatewayFilter Factory采用一对名称和值作为参数application.yml.spring:

cloud:

gateway:

routes:

- id: add_request_header_route

uri: http://example.org

filters:

- AddResponseHeader=X-Response-Foo, Bar复制对于所有匹配的请求,这会将x-response-foo:bar头添加到下游响应的header中5.4 Hystrix GatewayFilter FactoryHystrix 是Netflix开源的断路器组件。Hystrix GatewayFilter允许你向网关路由引入断路器,保护你的服务不受级联故障的影响,并允许你在下游故障时提供fallback响应。要在项目中启用Hystrix网关过滤器,需要添加对 spring-cloud-starter-netflix-hystrix的依赖 Spring Cloud Netflix.Hystrix GatewayFilter Factory 需要一个name参数,即HystrixCommand的名称。application.yml.spring:

cloud:

gateway:

routes:

- id: hystrix_route

uri: http://example.org

filters:

- Hystrix=myCommandName复制这将剩余的过滤器包装在命令名为“myCommandName”的HystrixCommand中。hystrix过滤器还可以接受可选的fallbackUri 参数。目前,仅支持forward: 预设的URI,如果调用fallback,则请求将转发到与URI匹配的控制器。application.yml.spring:

cloud:

gateway:

routes:

- id: hystrix_route

uri: lb://backing-service:8088

predicates:

- Path=/consumingserviceendpoint

filters:

- name: Hystrix

args:

name: fallbackcmd

fallbackUri: forward:/incaseoffailureusethis

- RewritePath=/consumingserviceendpoint, /backingserviceendpoint复制当调用hystrix fallback时,这将转发到/incaseoffailureusethis uri。注意,这个示例还演示了(可选)通过目标URI上的'lb`前缀,使用Spring Cloud Netflix Ribbon 客户端负载均衡。主要场景是使用fallbackUri 到网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如:application.yml.spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: Hystrix

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback复制在本例中,gateway应用程序中没有 fallback 实现,但是另一个应用程序中有一个接口实现,注册为“http://localhost:9994”。在将请求转发到fallback的情况下,Hystrix Gateway过滤还支持直接抛出Throwable 。它被作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange中,可以在处理网关应用程序中的fallback时使用。对于外部控制器/处理程序方案,可以添加带有异常详细信息的header。可以在 FallbackHeaders GatewayFilter Factory section.中找到有关它的更多信息。hystrix配置参数(如 timeouts)可以使用全局默认值配置,也可以使用Hystrix wiki中所述属性进行配置。要为上面的示例路由设置5秒超时,将使用以下配置:application.yml.hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000复制5.5 FallbackHeaders GatewayFilter FactoryFallbackHeaders允许在转发到外部应用程序中的FallbackUri的请求的header中添加Hystrix异常详细信息,如下所示:application.yml.spring:

cloud:

gateway:

routes:

- id: ingredients

uri: lb://ingredients

predicates:

- Path=//ingredients/**

filters:

- name: Hystrix

args:

name: fetchIngredients

fallbackUri: forward:/fallback

- id: ingredients-fallback

uri: http://localhost:9994

predicates:

- Path=/fallback

filters:

- name: FallbackHeaders

args:

executionExceptionTypeHeaderName: Test-Header复制在本例中,在运行HystrixCommand发生执行异常后,请求将被转发到 localhost:9994应用程序中的 fallback终端或程序。异常类型、消息(如果可用)cause exception类型和消息的头,将由FallbackHeaders filter添加到该请求中。通过设置下面列出的参数值及其默认值,可以在配置中覆盖headers的名称: executionExceptionTypeHeaderName ("Execution-Exception-Type") executionExceptionMessageHeaderName ("Execution-Exception-Message") rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type") rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")Hystrix 如何实现的更多细节可以参考 Hystrix GatewayFilter Factory section.5.6 PrefixPath GatewayFilter FactoryPrefixPath GatewayFilter 只有一个 prefix 参数.application.yml.spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: http://example.org

filters:

- PrefixPath=/mypath复制这将给所有匹配请求的路径加前缀/mypath。因此,向/hello发送的请求将发送到/mypath/hello。5.7 PreserveHostHeader GatewayFilter Factory该filter没有参数。设置了该Filter后,GatewayFilter将不使用由HTTP客户端确定的host header ,而是发送原始host header 。application.yml.spring:

cloud:

gateway:

routes:

- id: preserve_host_route

uri: http://example.org

filters:

- PreserveHostHeader复制5.8 RequestRateLimiter GatewayFilter FactoryRequestRateLimiter使用RateLimiter实现是否允许继续执行当前请求。如果不允许继续执行,则返回HTTP 429 - Too Many Requests (默认情况下)。这个过滤器可以配置一个可选的keyResolver 参数和rate limiter参数(见下文)。keyResolver 是 KeyResolver 接口的实现类.在配置中,按名称使用SpEL引用bean。#{@myKeyResolver} 是引用名为'myKeyResolver'的bean的SpEL表达式。KeyResolver.java.public interface KeyResolver {

Mono resolve(ServerWebExchange exchange);

}复制KeyResolver接口允许使用可插拔策略来派生限制请求的key。在未来的里程碑版本中,将有一些KeyResolver实现。KeyResolver的默认实现是PrincipalNameKeyResolver,它从ServerWebExchange检索Principal并调用Principal.getName()。默认情况下,如果KeyResolver 没有获取到key,请求将被拒绝。此行为可以使用 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) 和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性进行调整。 说明

无法通过"shortcut" 配置RequestRateLimiter。以下示例无效

application.properties.# INVALID SHORTCUT CONFIGURATION

spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}复制5.8.1 Redis RateLimiterRedis的实现基于 Stripe实现。它需要使用 spring-boot-starter-data-redis-reactive Spring Boot starter。使用的算法是Token Bucket Algorithm.。redis-rate-limiter.replenishRate是你允许用户每秒执行多少请求,而丢弃任何请求。这是令牌桶的填充速率。``redis-rate-limiter.burstCapacity`是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。将此值设置为零将阻止所有请求。稳定速率是通过在replenishRate 和 burstCapacity中设置相同的值来实现的。可通过设置burstCapacity高于replenishRate来允许临时突发流浪。在这种情况下,限流器需要在两次突发之间留出一段时间(根据replenishRate),因为连续两次突发将导致请求丢失 (HTTP 429 - Too Many Requests).。application.yml.spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: http://example.org

filters:

- name: RequestRateLimiter

args:

redis-rate-limiter.replenishRate: 10

redis-rate-limiter.burstCapacity: 20复制Config.java.@Bean

KeyResolver userKeyResolver() {

return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));

}复制这定义了每个用户10个请求的限制。允许20个突发,但下一秒只有10个请求可用。KeyResolver是一个简单的获取user请求参数的工具(注意:不建议用于生产)。限流器也可以定义为RateLimiter接口的实现 bean。在配置中,按名称使用SpEL引用bean。#{@myRateLimiter}是引用名为'myRateLimiter'的bean的SpEL表达式。application.yml.spring:

cloud:

gateway:

routes:

- id: requestratelimiter_route

uri: http://example.org

filters:

- name: RequestRateLimiter

args:

rate-limiter: "#{@myRateLimiter}"

key-resolver: "#{@userKeyResolver}"复制5.9 RedirectTo GatewayFilter Factory该过滤器有一个 status 和一个 url参数。status是300类重定向HTTP代码,如301。该URL应为有效的URL,这将是 Location header的值。application.yml.spring:

cloud:

gateway:

routes:

- id: prefixpath_route

uri: http://example.org

filters:

- RedirectTo=302, http://acme.org复制这将发送一个302状态码和一个Location:http://acme.org header来执行重定向。5.10 RemoveNonProxyHeaders GatewayFilter FactoryRemoveNonProxyHeaders GatewayFilter Factory 从转发请求中删除headers。删除的默认头列表来自 IETF.The default removed headers are:ConnectionKeep-AliveProxy-AuthenticateProxy-AuthorizationTETrailerTransfer-EncodingUpgrade

要更改此设置,请将 spring.cloud.gateway.filter.remove-non-proxy-headers.headers属性设置为要删除的header名称。5.11 RemoveRequestHeader GatewayFilter Factory有一个name参数. 这是要删除的header的名称。application.yml.spring:

cloud:

gateway:

routes:

- id: removerequestheader_route

uri: http://example.org

filters:

- RemoveRequestHeader=X-Request-Foo复制这将在X-Request-Foo header被发送到下游之前删除它。5.12 RemoveResponseHeader GatewayFilter Factory有一个name参数. 这是要删除的header的名称。application.yml.spring:

cloud:

gateway:

routes:

- id: removeresponseheader_route

uri: http://example.org

filters:

- RemoveResponseHeader=X-Response-Foo复制这将在返回到网关client之前从响应中删除x-response-foo头。5.13 RewritePath GatewayFilter Factory包含一个 regexp正则表达式参数和一个 replacement 参数. 通过使用Java正则表达式灵活地重写请求路径。application.yml.spring:

cloud:

gateway:

routes:

- id: rewritepath_route

uri: http://example.org

predicates:

- Path=/foo/**

filters:

- RewritePath=/foo/(?.*), /$\{segment}复制对于请求路径/foo/bar,将在发出下游请求之前将路径设置为/bar。注意,由于YAML规范,请使用 $\替换 $。5.14 RewriteResponseHeader GatewayFilter Factory包含 name, regexp和 replacement 参数.。通过使用Java正则表达式灵活地重写响应头的值。application.yml.spring:

cloud:

gateway:

routes:

- id: rewriteresponseheader_route

uri: http://example.org

filters:

- RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***复制对于一个/42?user=ford&password=omg!what&flag=true的header值,在做下游请求时将被设置为/42?user=ford&password=***&flag=true,由于YAML规范,请使用 $\替换 $。5.15 SaveSession GatewayFilter FactorySaveSession GatewayFilter Factory将调用转发到下游之前强制执行WebSession::save 操作。这在使用 Spring Session 之类时特别有用,需要确保会话状态在进行转发调用之前已保存。application.yml.spring:

cloud:

gateway:

routes:

- id: save_session

uri: http://example.org

predicates:

- Path=/foo/**

filters:

- SaveSession复制如果你希望要将[Spring Security](https://projects.spring.io/Spring Security/)与Spring Session集成,并确保安全详细信息已转发到远程的进程,这一点至关重要。5.16 SecureHeaders GatewayFilter FactorySecureHeaders GatewayFilter Factory 将许多headers添加到reccomedation处的响应中,从this blog post.添加以下标题(使用默认值分配):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 to change:xss-protection-headerstrict-transport-securityframe-optionscontent-type-optionsreferrer-policycontent-security-policydownload-optionspermitted-cross-domain-policies5.17 SetPath GatewayFilter FactorySetPath GatewayFilter Factory 采用 template路径参数。它提供了一种通过允许路径的模板化segments来操作请求路径的简单方法。使用Spring Framework中的URI模板,允许多个匹配segments。application.yml.spring:

cloud:

gateway:

routes:

- id: setpath_route

uri: http://example.org

predicates:

- Path=/foo/{segment}

filters:

- SetPath=/{segment}复制对于一个 /foo/bar请求,在做下游请求前,路径将被设置为/bar5.18 SetResponseHeader GatewayFilter FactorySetResponseHeader GatewayFilter Factory 包括 name 和 value 参数.application.yml.spring:

cloud:

gateway:

routes:

- id: setresponseheader_route

uri: http://example.org

filters:

- SetResponseHeader=X-Response-Foo, Bar复制此GatewayFilter使用给定的名称替换所有header,而不是添加。因此,如果下游服务器响应为X-Response-Foo:1234,则会将其替换为X-Response-Foo:Bar,这是网关客户端将接收的内容。5.19 SetStatus GatewayFilter FactorySetStatus GatewayFilter Factory 包括唯一的 status参数.必须是一个可用的Spring HttpStatus。它可以是整数值404或字符串枚举NOT_FOUND。application.yml.spring:

cloud:

gateway:

routes:

- id: setstatusstring_route

uri: http://example.org

filters:

- SetStatus=BAD_REQUEST

- id: setstatusint_route

uri: http://example.org

filters:

- SetStatus=401复制在这个例子中,HTTP返回码将设置为401.5.20 StripPrefix GatewayFilter FactoryStripPrefix GatewayFilter Factory 包括一个parts参数。 parts参数指示在将请求发送到下游之前,要从请求中去除的路径中的节数。application.yml.spring:

cloud:

gateway:

routes:

- id: nameRoot

uri: http://nameservice

predicates:

- Path=/name/**

filters:

- StripPrefix=2复制当通过网关发出/name/bar/foo请求时,向nameservice发出的请求将是http://nameservice/foo。5.21 Retry GatewayFilter FactoryRetry GatewayFilter Factory包括 retries, statuses, methods和 series 参数. retries: 应尝试的重试次数 statuses: 应该重试的HTTP状态代码,用org.springframework.http.HttpStatus标识 methods: 应该重试的HTTP方法,用 org.springframework.http.HttpMethod标识 series: 要重试的一系列状态码,用 org.springframework.http.HttpStatus.Series标识application.yml.spring:

cloud:

gateway:

routes:

- id: retry_test

uri: http://localhost:8080/flakey

predicates:

- Host=*.retry.com

filters:

- name: Retry

args:

retries: 3

statuses: BAD_GATEWAY 注意

retry filter 不支持body请求的重试,如通过body的POST 或 PUT请求

注意

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

5.22 RequestSize GatewayFilter Factory当请求大小大于允许的限制时,RequestSize GatewayFilter Factory可以限制请求不到达下游服务。过滤器以RequestSize作为参数,这是定义请求的允许大小限制(以字节为单位)。application.yml.spring:

cloud:

gateway:

routes:

- id: request_size_route

uri: http://localhost:8080/upload

predicates:

- Path=/upload

filters:

- name: RequestSize

args:

maxSize: 5000000复制当请求因大小而被拒绝时, RequestSize GatewayFilter Factory 将响应状态设置为413 Payload Too Large,并带有额外的header errorMessage 。下面是一个 errorMessage的例子。errorMessage : Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB 注意

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

5.23 Modify Request Body GatewayFilter Factory这个过滤器被定义为beta版本,将来API可能会改变。此过滤器可用于在请求主体被网关发送到下游之前对其进行修改。 注意

只能使用Java DSL配置此过滤器

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,

(exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))

.build();

}

static class Hello {

String message;

public Hello() { }

public Hello(String message) {

this.message = message;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}复制5.24 Modify Response Body GatewayFilter Factory这个过滤器被定义为beta版本,将来API可能会改变。

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

只能使用Java DSL配置此过滤器

@Bean

public RouteLocator routes(RouteLocatorBuilder builder) {

return builder.routes()

.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")

.filters(f -> f.prefixPath("/httpbin")

.modifyResponseBody(String.class, String.class,

(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)

.build();

}复制6. Global FiltersGlobalFilter接口与GatewayFilter具有相同的签名。是有条件地应用于所有路由的特殊过滤器。(此接口和用法可能在将来的里程碑版本中发生更改)。6.1 全局Filter和GatewayFilter组合排序当请求进入(并与路由匹配)时,筛选Web Handler 会将GlobalFilter的所有实例和所有的GatewayFilter路由特定实例添加到 filter chain。filter组合的排序由org.springframework.core.Ordered接口决定,可以通过实现getOrde()方法或使用@Order注释来设置。由于Spring Cloud Gateway将用于执行过滤器逻辑区分为“前置”和“后置”阶段,具有最高优先级的过滤器将是“前置”阶段的第一个,而“后置”阶段的最后一个。ExampleConfiguration.java.@Bean

@Order(-1)

public GlobalFilter a() {

return (exchange, chain) -> {

log.info("first pre filter");

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

log.info("third post filter");

}));

};

}

@Bean

@Order(0)

public GlobalFilter b() {

return (exchange, chain) -> {

log.info("second pre filter");

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

log.info("second post filter");

}));

};

}

@Bean

@Order(1)

public GlobalFilter c() {

return (exchange, chain) -> {

log.info("third pre filter");

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

log.info("first post filter");

}));

};

}复制6.2 Forward Routing FilterForwardRoutingFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一个forwardscheme (如 forward:///localendpoint),它将使用Spring DispatcherHandler 来处理请求。请求URL的路径部分将被转发URL中的路径覆盖。未修改的原始URL将附加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。6.3 LoadBalancerClient FilterLoadBalancerClientFilter在exchange属性ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中查找URI。如果URL有一个lbscheme (如 lb://myservice),它将使用Spring Cloud LoadBalancerClient 将名称(在前一个示例中为'myservice)解析为实际主机和端口,并替换URI。未修改的原始URL将附加到ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中的列表中。过滤器还将查看ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性,查看它是否等于lb`,然后应用相同的规则。application.yml.spring:

cloud:

gateway:

routes:

- id: myRoute

uri: lb://service

predicates:

- Path=/service/**复制 注意

默认情况下,如果一个服务实例在LoadBalancer 中没有发现,则返回503。可以通过设置spring.cloud.gateway.loadbalancer.use404=true来让网管返回404.

注意

从LoadBalancer返回的ServiceInstance的isSecure 值将覆盖在对网关发出的请求中指定的scheme。例如,如果请求通过HTTPS进入网关,但ServiceInstance表示它不安全,则下游请求将通过HTTP协议。相反的情况也适用。但是,如果在网关配置中为路由指定了GATEWAY_SCHEME_PREFIX_ATTR,则前缀将被删除,并且路由URL生成的scheme将覆盖ServiceInstance配置。6.4 Netty Routing Filter如果位于 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性中的URL具有http 或https 模式,则会运行Netty Routing Filter。它使用Netty HttpClient 发出下游代理请求。响应放在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性中,以便在以后的过滤器中使用。(有一个实验阶段不需要Netty的相同的功能的Filter,WebClientHttpRoutingFilter)6.5 Netty Write Response Filter如果ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange属性中存在 Netty HttpClientResponse,则运行 NettyWriteResponseFilter 。它在其他所有过滤器完成后将代理响应写回网关客户端响应之后运行。(有一个不需要netty的实验性的WebClientWriteResponseFilter执行相同的功能)6.6 RouteToRequestUrl Filter如果ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange属性中存在Route对象,RouteToRequestUrlFilter将运行。它基于请求URI创建一个新的URI,使用Route对象的uri属性进行更新。新的URI被放置在ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange属性中。如果该URI有一个前缀scheme,例如lb:ws://serviceid,则会从该URI中剥离该 lb scheme,并将其放置在ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR中,以便稍后在过滤器链中使用。6.7 Websocket Routing Filter如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTRexchange属性中有 ws 、 wssscheme,则Websocket Routing Filter将被运行。它使用Spring Web Socket基础模块将Websocket转发到下游。URI前缀为lb的Websockets可以被负载均衡,如 lb:ws://serviceid. 注意

如果使用 SockJS 作为普通HTTP的fallback,则应配置普通HTTP路由以及WebSocket路由。

application.yml.spring:

cloud:

gateway:

routes:

# SockJS route

- id: websocket_sockjs_route

uri: http://localhost:3001

predicates:

- Path=/websocket/info/**

# Normwal Websocket route

- id: websocket_route

uri: ws://localhost:3001

predicates:

- Path=/websocket/**复制6.8 Gateway Metrics Filter要启用网关指标,请将spring-boot-starter-actuator添加为项目依赖项。然后,默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关指标过滤器就会运行。此过滤器添加名为“gateway.requests”的计时器指标,并带有以下标记: routeId: The route id routeUri: API 将被转发的URI outcome: 结果分类依据 HttpStatus.Series status: 返回client的请求的Http Status这些指标可以从/actuator/metrics/gateway.requests中获取,可以很容易地与Prometheus集成以创建Grafana dashboard. 注意

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

6.9 Making An Exchange As Routed网关路由ServerWebExchange之后,它将通过向Exchange属性添加gatewayAlreadyRouted,将该exchange标记为“routed”。一旦一个请求被标记为routed,其他路由过滤器将不会再次路由该请求,将跳过该过滤器。有一些方便的方法可以用来将exchange标记为routed,或者检查exchange是否已经routed。 ServerWebExchangeUtils.isAlreadyRouted 有一个 ServerWebExchange对象并检查它是否已"routed" ServerWebExchangeUtils.setAlreadyRouted 有一个 ServerWebExchange 对象并将其标记为"routed"7. TLS / SSL网关可以通过常规的 Spring server configuration 来侦听HTTPS上的请求。例子:application.yml.server:

ssl:

enabled: true

key-alias: scg

key-store-password: scg1234

key-store: classpath:scg-keystore.p12

key-store-type: PKCS12复制网关路由可以路由到HTTP和HTTPS后端。如果路由到HTTPS后端,则可以将网关配置为信任所有具有证书的下游服务:application.yml.spring:

cloud:

gateway:

httpclient:

ssl:

useInsecureTrustManager: true复制不建议在生产环境使用不安全的信任管理器。对于生产部署,可以使用一组已知证书配置网关,这些证书可以通过以下方式进行配置:application.yml.spring:

cloud:

gateway:

httpclient:

ssl:

trustedX509Certificates:

- cert1.pem

- cert2.pem复制如果Spring Cloud Gateway未配置受信任证书,则使用默认信任库(可以使用系统属性javax.net.ssl.trustStore覆盖)。7.1 TLS 握手网关维护一个用于路由到后端的client池。当通过HTTPS通信时,客户端启动一个TLS握手,其中可能会有很多超时。这些超时可以这样配置(显示默认值):application.yml.spring:

cloud:

gateway:

httpclient:

ssl:

handshake-timeout-millis: 10000

close-notify-flush-timeout-millis: 3000

close-notify-read-timeout-millis: 0复制8. ConfigurationSpring Cloud Gateway的配置由RouteDefinitionLocator的集合驱动。RouteDefinitionLocator.java.public interface RouteDefinitionLocator {

Flux getRouteDefinitions();

}复制默认情况下,PropertiesRouteDefinitionLocator使用Spring Boot的@ConfigurationProperties机制加载属性。以下两个示例是等效的:application.yml.spring:

cloud:

gateway:

routes:

- id: setstatus_route

uri: http://example.org

filters:

- name: SetStatus

args:

status: 401

- id: setstatusshortcut_route

uri: http://example.org

filters:

- SetStatus=401复制对于网关的大部分用法,配置文件方式是够用的,但一些生产用例更建议从外部源(如数据库)加载配置。未来的里程碑版本将有基于Spring Data Repositories (如Redis、MongoDB和Cassandra)的RouteDefinitionLocator实现。8.1 Fluent Java Routes API为了可以更简单在Java中配置,在RouteLocatorBuilder bean中定义了一个fluent API。GatewaySampleApplication.java.// static imports from GatewayFilters and RoutePredicates

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {

return builder.routes()

.route(r -> r.host("**.abc.org").and().path("/image/png")

.filters(f ->

f.addResponseHeader("X-TestHeader", "foobar"))

.uri("http://httpbin.org:80")

)

.route(r -> r.path("/image/webp")

.filters(f ->

f.addResponseHeader("X-AnotherHeader", "baz"))

.uri("http://httpbin.org:80")

)

.route(r -> r.order(-1)

.host("**.throttle.org").and().path("/get")

.filters(f -> f.filter(throttle.apply(1,

1,

10,

TimeUnit.SECONDS)))

.uri("http://httpbin.org:80")

)

.build();

}复制这种样式还允许使用更多的自定义断言。由RouteDefinitionLocator beans定义的断言使用逻辑 and组合。通过使用fluent Java API,可以在 Predicate类上使用 and()、or() 、 negate()运算符。8.2 DiscoveryClient Route Definition Locator可以将网关配置为基于使用兼容DiscoveryClient注册中心注册的服务来创建路由。要启用此功能,请设置spring.cloud.gateway.discovery.locator.enabled=true,并确保DiscoveryClient实现位于classpath上并已启用(如netflix eureka、consul或zookeeper)。8.2.1 Configuring Predicates and Filters For DiscoveryClient Routes默认情况下,网关为通过DiscoveryClient创建的路由定义单个断言和过滤器。默认断言是使用/serviceId/**定义的path断言,其中serviceId是DiscoveryClient中服务的ID。默认过滤器是使用正则表达式 /serviceId/(?.*)和替换的/${remaining}进行重写。这只是在请求被发送到下游之前从路径中截取掉 service id 。可以通过设置spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]来实现自定义DiscoveryClient路由使用的断言and/or过滤器。当你这样做时,如果你想要保留这个功能,你需要确保包括上面的默认断言和过滤器。下面是这样一个例子。application.properties.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 + '/(?.*)'"

spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"复制9. Reactor Netty Access Logs设置 -Dreactor.netty.http.server.accessLogEnabled=true 来开启Reactor Netty access logs,注意必须是Java System Property而不是Spring Boot property。logging 模块也可以通过配置单独输出一个access log文件,下面是logback的配置例子:logback.xml.

access_log.log

%msg%n

复制10. CORS Configuration我们可以通过配置网关来控制CORS行为,全局CORS配置是 Spring Framework CorsConfiguration模式的URL MAP。application.yml.spring:

cloud:

gateway:

globalcors:

corsConfigurations:

'[/**]':

allowedOrigins: "http://docs.spring.io"

allowedMethods:

- GET复制例子中将允许从docs.spring.io发出的所有GET请求进行CORS请求。11. Actuator API/gateway的actuator端点允许监视Spring Cloud Gateway应用程序并与之交互。要进行远程访问,必须在应用程序属性中暴露HTTP或JMX 端口。application.properties.management.endpoint.gateway.enabled=true # default value

management.endpoints.web.exposure.include=gateway复制11.1 Retrieving route filters11.1.1 Global Filters要检索应用于所有路由的 [global filters],请get请求 /actuator/gateway/globalfilters。返回的结果类似于以下内容:{

"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

}复制返回结果包含已就绪的global filters的详细信息(如 org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5)。对于每个global filters,返回结果字符串对应过滤器链中的相应顺序。11.1.2 Route Filters要检索应用于路由的 [GatewayFilter factories] ,请get请求/actuator/gateway/routefilters。返回结果类似于以下内容:{

"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,

"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,

"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null

}复制返回结果包含应用于所有路由的GatewayFilter的详细信息。显示每个工厂提供字符串格式的相应对象(例如, [SecureHeadersGatewayFilterFactory@fceab5d configClass = Object])。请注意,null值是由于endpoint controller实现不完整造成的,因为它尝试在filter chain中设置对象的顺序,这不适用于GatewayFilter工厂对象。11.2 Refreshing the route cache如果要清理路由的缓存,请POST请求/actuator/gateway/refresh。该请求将返回一个没有body的200返回码。11.3 Retrieving the routes defined in the gateway要检索网关中定义的路由,发送GET请求/actuator/gateway/routes,返回结果如下所示:[{

"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

}]复制返回结果中包含网关中所有定义的路由信息,下面表格中描述了返回结果信息:image.png11.4 Retrieving information about a particular route要获取单个路由的信息,发送GET请求 /actuator/gateway/routes/{id} (如: /actuator/gateway/routes/first_route),返回结果如下所示:{

"id": "first_route",

"predicates": [{

"name": "Path",

"args": {"_genkey_0":"/first"}

}],

"filters": [],

"uri": "http://www.uri-destination.org",

"order": 0

}]复制下面表格中描述了返回结果信息:image.png11.5 Creating and deleting a particular route要创建一个路由,发送POST请求 /gateway/routes/{id_route_to_create},参数为JSON结构,具体参数数据结构参考上面章节。要删除一个路由,发送 DELETE请求 /gateway/routes/{id_route_to_delete}。11.6 Recap: list of all endpoints下表总结了Spring Cloud Gateway actuator endpoints。注意,每个endpoint都是/actuator/gateway作为基本路径。image.png12. Developer GuideTODO: overview of writing custom integrations12.1 Writing Custom Route Predicate FactoriesTODO: document writing Custom Route Predicate Factories12.2 Writing Custom GatewayFilter Factories如果要自定义一个GatewayFilter,需要实现GatewayFilterFactory。下面是一个你需要集成的抽象类 AbstractGatewayFilterFactory。PreGatewayFilterFactory.java.public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PreGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

//If you want to build a "pre" filter you need to manipulate the

//request before calling chain.filter

ServerHttpRequest.Builder builder = exchange.getRequest().mutate();

//use builder to manipulate the request

return chain.filter(exchange.mutate().request(request).build());

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}复制PostGatewayFilterFactory.java.public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory {

public PostGatewayFilterFactory() {

super(Config.class);

}

@Override

public GatewayFilter apply(Config config) {

// grab configuration from Config object

return (exchange, chain) -> {

return chain.filter(exchange).then(Mono.fromRunnable(() -> {

ServerHttpResponse response = exchange.getResponse();

//Manipulate the response in some way

}));

};

}

public static class Config {

//Put the configuration properties for your filter here

}

}复制12.3 Writing Custom Global FiltersTODO: document writing Custom Global Filters12.4 Writing Custom Route Locators and WritersTODO: document writing Custom Route Locators and Writers 个人介绍:

高广超:多年一线互联网研发与架构设计经验,擅长设计与落地高可用、高性能、可扩展的互联网架构。目前从事大数据相关研发与架构工作。本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。 原始发表:2019.03.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除前往查看spring cloud本文分享自 作者个人站点/博客 前往查看如有侵权,请联系 cloudcommunity@tencent.com 删除。本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!spring cloud评论登录后参与评论0 条评论热度最新登录 后参与评论推荐阅读LV.关注文章0获赞0目录1. 如何在工程中引用Spring Cloud Gateway2. 词汇表3. 如何工作的4. 路由断言Factories4.1 After 路由断言 Factory4.2 Before 路由断言 Factory4.3 Between 路由断言 Factory4.4 Cookie 路由断言 Factory4.5 Header 路由断言 Factory4.6 Host 路由断言 Factory4.7 Method 路由断言 Factory4.8 Path 路由断言 Factory4.9 Query 路由断言 Factory4.10 RemoteAddr 路由断言 Factory4.10.1 修改远程地址的解析方式5. GatewayFilter Factories5.1 AddRequestHeader GatewayFilter Factory5.2 AddRequestParameter GatewayFilter Factory5.3 AddResponseHeader GatewayFilter Factory5.4 Hystrix GatewayFilter Factory5.5 FallbackHeaders GatewayFilter Factory5.6 PrefixPath GatewayFilter Factory5.7 PreserveHostHeader GatewayFilter Factory5.8 RequestRateLimiter GatewayFilter Factory5.8.1 Redis RateLimiter5.9 RedirectTo GatewayFilter Factory5.10 RemoveNonProxyHeaders GatewayFilter Factory5.11 RemoveRequestHeader GatewayFilter Factory5.12 RemoveResponseHeader GatewayFilter Factory5.13 RewritePath GatewayFilter Factory5.14 RewriteResponseHeader GatewayFilter Factory5.15 SaveSession GatewayFilter Factory5.16 SecureHeaders GatewayFilter Factory5.17 SetPath GatewayFilter Factory5.18 SetResponseHeader GatewayFilter Factory5.19 SetStatus GatewayFilter Factory5.20 StripPrefix GatewayFilter Factory5.21 Retry GatewayFilter Factory5.22 RequestSize GatewayFilter Factory5.23 Modify Request Body GatewayFilter Factory5.24 Modify Response Body GatewayFilter Factory6. Global Filters6.1 全局Filter和GatewayFilter组合排序6.2 Forward Routing Filter6.3 LoadBalancerClient Filter6.4 Netty Routing Filter6.5 Netty Write Response Filter6.6 RouteToRequestUrl Filter6.7 Websocket Routing Filter6.8 Gateway Metrics Filter6.9 Making An Exchange As Routed7. TLS / SSL7.1 TLS 握手8. Configuration8.1 Fluent Java Routes API8.2 DiscoveryClient Route Definition Locator8.2.1 Configuring Predicates and Filters For DiscoveryClient Routes9. Reactor Netty Access Logs10. CORS Configuration11. Actuator API11.1 Retrieving route filters11.1.1 Global Filters11.1.2 Route Filters11.2 Refreshing the route cache11.3 Retrieving the routes defined in the gateway11.4 Retrieving information about a particular route11.5 Creating and deleting a particular route11.6 Recap: list of all endpoints12. Developer Guide12.1 Writing Custom Route Predicate Factories12.2 Writing Custom GatewayFilter Factories12.3 Writing Custom Global Filters12.4 Writing Custom Route Locators and Writers相关产品与服务云数据库 Redis腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。产品介绍产品文档云数据库采购特惠,高性能、高可靠、高安全,超值优惠等你享!

领券社区专栏文章阅读清单互动问答技术沙龙技术视频团队主页腾讯云TI平台活动自媒体分享计划邀请作者入驻自荐上首页技术竞赛资源技术周刊社区标签开发者手册开发者实验室关于社区规范免责声明联系我们友情链接腾讯云开发者扫码关注腾讯云开发者领取腾讯云代金券热门产品域名注册云服务器区块链服务消息队列网络加速云数据库域名解析云存储视频直播热门推荐人脸识别腾讯会议企业云CDN加速视频通话图像分析MySQL 数据库SSL 证书语音识别更多推荐数据安全负载均衡短信文字识别云点播商标注册小程序开发网站监控数据迁移Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有 深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569腾讯云计算(北京)有限责任公司 京ICP证150476号 |  京ICP备11018762号 | 京公网安备号11010802020287问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档Copyright © 2013 - 2024 Tencent Cloud.All Rights Reserved. 腾讯云 版权所有登录 后参与评论100

SpringCloud(九)手把手教你使用Getway新一代服务网关 - 知乎

SpringCloud(九)手把手教你使用Getway新一代服务网关 - 知乎切换模式写文章登录/注册SpringCloud(九)手把手教你使用Getway新一代服务网关知乎用户0I3Pz0Gateway简介 官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter什么是API 网关?是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。API 网关都有哪些职能,能干嘛?反向代理鉴权流量控制熔断:重试、安全、日志监控/指标等等.....API 网关的分类与功能?Gateway是什么Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。Spring Cloud 全家桶中,有个很重要的组件,就是网关(Getway):在 1.x 版本中都是采用的 Zuul 网关。2.x 中,使用 SpringCloud Getway 代替了 Zuul。一句话:SpringCloud Getway 使用的 WebFlux 框架实现的,而 WebFlux 框架底层使用了 高性能的 Reactor 模式通信框架 Netty;(异步非阻塞,性能高)为什么用GatewaySpring Cloud Gateway 可以看做是一个 Zuul 1.x 的升级版和代替品,比 Zuul 2 更早的使用 Netty 实现异步 IO,从而实现了一个简单、比 Zuul 1.x 更高效的、与 Spring Cloud 紧密配合的 API 网关。Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用。比如内置了 10 种 Router,使得我们可以直接配置一下就可以随心所欲的根据 Header、或者 Path、或者 Host、或者 Query 来做路由。比如区分了一般的 Filter 和全局 Filter,内置了 20 种 Filter 和 9 种全局 Filter,也都可以直接用。当然自定义 Filter 也非常方便。微服务架构中,网关在哪里:(网关是 所有 微服务的 入口)最重要的几个概念Route(路由):这是网关的基本构建块,它由一个ID,一个URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。Predicate(断言):输入类类是一个ServerWebExchange。我们可以使用它来匹配来自HTTP请求的任何内容,例如headers。如果请求与断言相匹配则进行路由。说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。Filter(过滤器):Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者后对请求进行修改。Gateway 工作流程客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( "pre" )或之后( "post" )执行业务逻辑。Filter在"pre" 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。核心逻辑:路由转发 + 执行过滤链1.集成Gateway入门配置1.1建立module: springcloud-gateway-gateway95271.2pom.xml主要还是新增了gateway的依赖。采坑提示,不要引入web依赖,不然会报错,项目都起不来。如下:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

springcloud

com.dyh.springcloud

1.0-SNAPSHOT

4.0.0

springcloud-gateway-gateway9527

org.springframework.cloud

spring-cloud-starter-gateway

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

com.dyh.springcloud

springcloud-api-commons

${project.version}

org.springframework.boot

spring-boot-starter-actuator

org.projectlombok

lombok

true

1.3.application.ymlserver:

port: 9527

spring:

application:

name: springcloud-gateway

eureka:

instance:

hostname: springcloud-gateway-service

client: #服务提供者provider注册进eureka服务列表内

service-url:

register-with-eureka: true

fetch-registry: true

defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/1.4.主启动类 GatewayMainimport org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication

@EnableEurekaClient

public class GatewayMain {

public static void main(String[] args) {

SpringApplication.run(GatewayMain.class, args);

}

}1.5.测试那接下去启动Eureka7001,Eureka7002服务和我们新建的Gateway的网关服务,看看网关服务是否成功注册到Eureka注册中心?可以看到网关Gateway成功的注册了注册中心,那网关如何做映射呢?那我们以springcloud-provider-payment8001生产者服务为例来映射一下。打开PaymentControler控制层,对get方法进行演示,因为我们之前访问都是http://localhost:8001/payment/get/1的访问,但是我们访问的时候是将我们的端口8001,暴露在了外边,不安全,但是我们不想暴露真的8001端口号,希望在外面8001外边包上一层我们的Gateway的端口9527,这就需要在yml配置新增路由配置。如下:server:

port: 9527

spring:

application:

name: springcloud-gateway

cloud:

gateway:

routes:

- id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名

uri: http://localhost:8001

predicates:

- Path=/payment/get/** # 断言,路径相匹配的进行路由

eureka:

instance:

hostname: springcloud-gateway-service

client: #服务提供者provider注册进eureka服务列表内

service-url:

register-with-eureka: true

fetch-registry: true

defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

然后我们访问http://localhost:9527/payment/get/1,可以成功访问,说明我们的网关的路由和断言就配置成功啦!如下图:我们现在配置的是YML进行配置的,还有一种配置方案就是通过硬编码的方式。就是代码中注入RouteLocator的Bean,是为了解决YML文件配置太多,文件太大的问题。那就开始撸起来吧!我们只要演示通过9527网关访问到外网的百度新闻网址。新建一个config配置文件,如下:import org.springframework.cloud.gateway.route.RouteLocator;

import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

* 配置了一个id为routr-name的路由规则

* 当访问地址http://localhost:9527/guonei时会自动转发到http://news.baidu.com/guonei

*/

@Configuration

public class GateWayConfig {

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {

RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

routes.route("patn_route_buba", r -> r.path("/guonei")

.uri("http://news.baidu.com/guonei")).build();

return routes.build();

}

}配置完毕,重新启动服务,我们访问http://localhost:9527/guonei,可以成功转发到如下界面,说明我们GateWay通过编码的方式进行路由的映射配置。2.集成Gateway实现动态路由看我们的YML配置文件,我们配置的是http://localhost:8001是写死的,但是在我们微服务中生产者服务是不可能有一台机器的,所以说必须要进行负载均衡的配置。实现负载均衡需要此依赖 - 后续yml配置会以 lb(动态路由协议) 开头 默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。那我们就需要修改Gateway的YML配置文件,开启从注册中心动态创建路由的功能,利用微服务名称进行路由,匹配后提供服务的路由地址修改为生产者的服务名称,具体配置如下:server:

port: 9527

spring:

application:

name: springcloud-gateway

cloud:

gateway:

# locator需要打开,不然通过 lb://.. 方式请求不到

locator:

enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称进行路由

routes:

- id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名

#匹配后提供服务的路由地址

#uri: http://localhost:8001

#lb是一个动态路由协议,后面的SPRINGCLOUD-PAYMENT-SERVICE是要跳转的服务名称。

uri: lb://SPRINGCLOUD-PAYMENT-SERVICE

predicates:

- Path=/payment/get/** # 断言,路径相匹配的进行路由

eureka:

instance:

hostname: springcloud-gateway-service

client: #服务提供者provider注册进eureka服务列表内

service-url:

register-with-eureka: true

fetch-registry: true

defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/为了测试负载均衡,我们需要启动Eureka7001,Eureka7002启动生产者服务8001和8002,启动Gateway9527服务,要记得在8002服务中也加上返回端口的get方法。访问http://localhost:9527/payment/get/1成功的实现了负载均衡。测试如下:PS:报错图片:此处遇到个问题,lb在eureka中查找SPRINGCLOUD-PAYMENT-SERVICE这个服务名下的实例时,我8001没有将ip显示出来,访问http://localhost:9527/payment/get/1就一直报错,8002显示出来,访问http://localhost:9527/payment/get/1就成功了(默认是轮询,轮到8002成功,8001报错)由此看出,用名称查找依赖服务发现,8001,8002主启动类加上@EnableDiscoveryClient注解,8001,8002yml文件加上prefer-ip-address: true #访问路径可以显示IP地址即可.就这样终于成功访问到8001,8002,实现了负载均衡,美滋滋。。。。。3.常用的Predicate断言我们启动我们的springcloud-gateway-gateway9527的服务,可以看到控制台有如下的界面:Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础框架的一部分,它包含许多内置的RoutePredicateFactory,所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂进行组合。Spring Cloud Gateway 创建Route对象时,使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route,Spring Cloud Gateway包含许多内置的Route Predicate Factoriess。所有的这些谓词都匹配HTTP的不同属性。多种谓工厂可以组合,并通过逻辑and。然后在我们的YML的配置文件也可以看到路由配置,我们使用的是path,就是请求的Path(路径)匹配配置值。如下图:我们常用的路由配置,就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。如下图:4.Filter的使用filter是Gateway的三大核心之一,路由过滤器可用于修改进入HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Gateway内置了多种路由过滤器,他们都由GatewayFilter工程类来产生。4.1Filter的作用当我们有很多个服务时,比如下图中的user-service、goods-service、sales-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如鉴权、限流、日志输出等。对于这样重复的工作,有没有办法做的更好,答案是肯定的。在微服务的上一层加一个全局的权限控制、限流、日志输出的Api Gatewat服务,然后再将请求转发到具体的业务服务层。这个Api Gateway服务就是起到一个服务边界的作用,外接的请求访问系统,必须先通过网关层。4.2Filter的生命周期Spring Cloud Gateway同zuul类似,生命周期只有pre和post。在路由处理之前,需要经过“pre”类型的过滤器处理,处理返回响应之后,可以由“post”类型的过滤器处理。在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等。比如上图中的user-service,收到业务服务的响应之后,再经过“post”类型的filter处理,最后返回响应到客户端。与zuul不同的是,filter除了分为“pre”和“post”两种方式的filter外,在Spring Cloud Gateway中,filter从作用范围可分为另外两种,一种是针对于单个路由的gateway filter,它在配置文件中的写法同predict类似;另外一种是针对于所有路由的global gateway filer。现在从作用范围划分的维度来讲解这两种filter。4.3Spring Cloud Gateway的Filter种类分为GatewayFilter(单一的)和GlobalFilter(全局的)Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter,二者区别如下:GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。4.4 GatewayFilter介绍GatewayFilter工厂同上一篇介绍的Predicate工厂类似,都是在配置文件application.yml中配置,遵循了约定大于配置的思想,只需要在配置文件配置GatewayFilter Factory的名称,而不需要写全部的类名,比如AddRequestHeaderGatewayFilterFactory只需要在配置文件中写AddRequestHeader,而不是全部类名。在配置文件中配置的GatewayFilter Factory最终都会相应的过滤器工厂类处理。Spring Cloud Gateway 内置的过滤器工厂一览表如下:每一个过滤器工厂在官方文档都给出了详细的使用案例,现在的版本有30种,点击查看官网,如果不清楚的还可以在org.springframework.cloud.gateway.filter.factory看每一个过滤器工厂的源码。编辑于 2022-04-14 13:48SpringSpring Cloud网关​赞同 8​​添加评论​分享​喜欢​收藏​申请

基于Gateway实现网关鉴权&分发 - 知乎

基于Gateway实现网关鉴权&分发 - 知乎首发于分布式与微服务切换模式写文章登录/注册基于Gateway实现网关鉴权&分发Coding小天才我看周围没人,原来我在山顶。Spring Cloud Gateway在不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接 口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:客户端会多次请求不同的微服务,增加了客户端的复杂性存在跨域请求,在一定场景下处理相对复杂认证复杂,每个服务都需要独立认证难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施俗话说的好:没有什么事情是不能加一个中间层解决的,如果有,那就加两个。这些问题也能通过加一个网关中间层来解决,这样所有的外部请求都会先经过网关这一层,也就是说微服务就不再需要考虑安全、性能、监控等问题,提高业务的灵活性和安全性。gateway官网:https://spring.io/projects/spring-cloud-gateway为什么有了Nginx还需要Gateway?nginx和Spring Cloud Gateway其实有许多功能重叠的地方,例如:限流、服务转发、数据缓存等,那为什么还要使用gateway来做网关呢?答案其实很简单:专人专职。其实,网关在大型微服务系统中是一个很重要的角色,在他的官方描述中:API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。 它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。 API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。而nginx只能实现一些上面所说的一部分功能,所以一般都是选择nginx做静态资源缓存和首页web服务器,在基于Nginx的首页高可用方案这篇文章中有详细描述,典型的架构图如下:网关架构图网关微服务搭建1、网关搭建和网关跨域搭建步骤:(1)在项目中,创建gateway_system模块,pom.xml:

org.springframework.cloud

spring-cloud-starter-gateway

org.springframework.cloud

spring-cloud-starter-netflix-hystrix

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

(2)创建包com.jerrychen.system, 创建引导类:GatewayApplication@SpringBootApplication

@EnableEurekaClient

public class GatewayApplication {

public static void main(String[] args) {

SpringApplication.run(GatewayApplication.class, args);

}

}(3)在resources下创建application.ymlspring:

application:

name: sysgateway

cloud:

gateway:

globalcors:

cors-configurations:

'[/**]': # 匹配所有请求

allowedOrigins: "*" #跨域处理 允许所有的域

allowedMethods: # 支持的方法

- GET

- POST

- PUT

- DELETE

routes:

#需要操作的服务id

- id: goods

#lb是一个动态路由协议,后面的goods是要跳转的服务名称。

如果链接中带goods,则根据lb在eureka中查找goods服务的真正访问路径。

uri: lb://goods

# 这个指定了如果需要操作goods服务的话,具体访问的信息

predicates:

- Path=/goods/**

# 如果转发路由请求后,忽略的第一个/后面的值,例如:localhost:9101/goods/1,

转发后为:localhost:9001/1 (goods服务端口为9001)

filters:

- StripPrefix= 1

# 添加登录服务的id

- id: system

uri: lb://system

predicates:

- Path=/system/**

filters:

- StripPrefix= 1

#服务端口

server:

port: 9101

#注册到服务注册中心

eureka:

client:

service-url:

defaultZone: http://127.0.0.1:6868/eureka

instance:

prefer-ip-address: true2、网关过滤我们可以通过网关过滤器,实现一些逻辑的处理,比如ip黑白名单拦截、特定地址的拦截等。下面的代码中做了两个过滤器,并且设定的先后顺序,只演示过滤器与运行效果。(1)gateway_system中创建IpFilter@Component

public class IpFilter implements GlobalFilter, Ordered {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

System.out.println("经过第1个过滤器IpFilter");

ServerHttpRequest request = exchange.getRequest();

InetSocketAddress remoteAddress = request.getRemoteAddress();

System.out.println("ip:"+remoteAddress.getHostName());

return chain.filter(exchange);

}

//过滤器顺序

@Override

public int getOrder() {

return 1;

}

}(2)gateway_system创建UrlFilter@Component

public class UrlFilter implements GlobalFilter, Ordered {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

System.out.println("经过第2个过滤器UrlFilter");

ServerHttpRequest request = exchange.getRequest();

String url = request.getURI().getPath();

System.out.println("url:"+url);

return chain.filter(exchange);

}

//过滤器顺序

@Override

public int getOrder() {

return 2;

}

}网关鉴权鉴权流程图由于在网关鉴权中会使用到JWT令牌,JWT涉及使用很多加密算法, 所以在这里做下扫盲, 简单了解就可以1、可逆加密算法与不可逆加密算法1.1、不可逆算法解释: 一旦加密就不能反向解密得到密码原文.种类: Hash加密算法, 散列算法, 摘要算法等用途:一般用于效验下载文件正确性,一般在网站上下载文件都能见到;存储用户敏感信息,如密码、 卡号等不可解密的信息。常见的不可逆加密算法有: MD5、SHA、HMAC1.2、可逆加密算法解释: 加密后, 密文可以反向解密得到密码原文.1.2.1 对称加密【文件加密和解密使用相同的密钥,即加密密钥也可以用作解密密钥】解释: 在对称加密算法中,数据发信方将明文和加密密钥一起经过特殊的加密算法处理后,使其变成复杂的加密密文发送出去,收信方收到密文后,若想解读出原文,则需要使用加密时用的密钥以及相同加密算法的逆算法对密文进行解密,才能使其回复成可读明文。在对称加密算法中,使用的密钥只有一个,收发双方都使用这个密钥,这就需要解密方事先知道加密密钥。优点: 对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。缺点: 没有非对称加密安全.用途: 一般用于保存用户手机号、身份证等敏感但能解密的信息。常见的对称加密算法有: AES、DES、3DES、Blowfish、IDEA、RC4、RC5、RC6、HS2561.2.2 非对称加密【两个密钥:公开密钥(publickey)和私有密钥,公有密钥加密,私有密钥解密】解释: 同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端.加密与解密:私钥加密,持有私钥或公钥才可以解密公钥加密,持有私钥才可解密签名:私钥签名, 持有公钥进行验证是否被篡改过.优点: 非对称加密与对称加密相比,其安全性更好;缺点: 非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。 用途: 一般用于签名和认证。私钥服务器保存, 用来加密, 公钥客户拿着用于对于令牌或者签名的解密或者校验使用.常见的非对称加密算法有: RSA、DSA(数字签名用)、ECC(移动设备用)、RS256 (采用SHA-256 的 RSA 签名)2、JWTJSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。头部(Header)头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。{"typ":"JWT","alg":"HS256"}在头部指明了签名算法是HS256算法。 我们进行BASE64编码http://base64.xpcha.com/,编码后的字符串如下:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9载荷(playload)载荷就是存放有效信息的地方。定义一个payload:{"sub":"1234567890","name":"John Doe","admin":true}后将其进行base64加密,得到Jwt的第二部分。eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9签证(signature)jwt的第三部分是一个签证信息,这个签证信息由三部分组成: header (base64后的) payload (base64后的) secret 这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ将这三部分用.连接成一个完整的字符串,构成了最终的jwt:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ3、实现鉴权单点登录流程图1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录

2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户

3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN

4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误3.1、在后台管理微服务中签发Token(1)、在后台管理微服务添加依赖

io.jsonwebtoken

jjwt

0.9.0

(2)在后台管理微服务中创建类: JwtUtilpackage com.changgou.system.util;

import io.jsonwebtoken.JwtBuilder;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;

import java.util.Date;

/**

* JWT工具类

*/

public class JwtUtil {

//有效期为

public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000 一个小时

//设置秘钥明文

public static final String JWT_KEY = "jerrychen";

/**

* 创建token

* @param id

* @param subject

* @param ttlMillis

* @return

*/

public static String createJWT(String id, String subject, Long ttlMillis) {

SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

long nowMillis = System.currentTimeMillis();

Date now = new Date(nowMillis);

if(ttlMillis==null){

ttlMillis=JwtUtil.JWT_TTL;

}

long expMillis = nowMillis + ttlMillis;

Date expDate = new Date(expMillis);

SecretKey secretKey = generalKey();

JwtBuilder builder = Jwts.builder()

.setId(id) //唯一的ID

.setSubject(subject) // 主题 可以是JSON数据

.setIssuer("admin") // 签发者

.setIssuedAt(now) // 签发时间

.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥

.setExpiration(expDate);// 设置过期时间

return builder.compact();

}

/**

* 生成加密后的秘钥 secretKey

* @return

*/

public static SecretKey generalKey() {

byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);

SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

return key;

}

}(3)修改AdminController的login方法, 用户登录成功 则 签发TOKEN/**

* 登录

* @param admin

* @return

*/

@PostMapping("/login")

public Result login(@RequestBody Admin admin){

boolean login = adminService.login(admin);

if(login){ //如果验证成功

Map info = new HashMap<>();

info.put("username",admin.getLoginName());

String token = JwtUtil.createJWT(UUID.randomUUID().toString(), admin.getLoginName(), null);

info.put("token",token);

return new Result(true, StatusCode.OK,"登录成功",info);

}else{

return new Result(false,StatusCode.LOGINERROR,"用户名或密码错误");

}

}(4)postman 测试3.2、在网关过滤器验证token(1)在gateway_system网关系统添加依赖

io.jsonwebtoken

jjwt

0.9.0

(2)创建JWTUtil类package com.changgou.gateway.util;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.Jwts;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;

/**

* jwt校验工具类

*/

public class JwtUtil {

//有效期为

public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000 一个小时

//设置秘钥明文

public static final String JWT_KEY = "jerrychen";

/**

* 生成加密后的秘钥 secretKey

*

* @return

*/

public static SecretKey generalKey() {

byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);

SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

return key;

}

/**

* 解析

*

* @param jwt

* @return

* @throws Exception

*/

public static Claims parseJWT(String jwt) throws Exception {

SecretKey secretKey = generalKey();

return Jwts.parser()

.setSigningKey(secretKey)

.parseClaimsJws(jwt)

.getBody();

}

}(3)创建过滤器,用于token验证/**

* 鉴权过滤器 验证token

*/

@Component

public class AuthorizeFilter implements GlobalFilter, Ordered {

private static final String AUTHORIZE_TOKEN = "token";

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

//1. 获取请求

ServerHttpRequest request = exchange.getRequest();

//2. 则获取响应

ServerHttpResponse response = exchange.getResponse();

//3. 如果是登录请求则放行

if (request.getURI().getPath().contains("/admin/login")) {

return chain.filter(exchange);

}

//4. 获取请求头

HttpHeaders headers = request.getHeaders();

//5. 请求头中获取令牌

String token = headers.getFirst(AUTHORIZE_TOKEN);

//6. 判断请求头中是否有令牌

if (StringUtils.isEmpty(token)) {

//7. 响应中放入返回的状态吗, 没有权限访问

response.setStatusCode(HttpStatus.UNAUTHORIZED);

//8. 返回

return response.setComplete();

}

//9. 如果请求头中有令牌则解析令牌

try {

JwtUtil.parseJWT(token);

} catch (Exception e) {

e.printStackTrace();

//10. 解析jwt令牌出错, 说明令牌过期或者伪造等不合法情况出现

response.setStatusCode(HttpStatus.UNAUTHORIZED);

//11. 返回

return response.setComplete();

}

//12. 放行

return chain.filter(exchange);

}

@Override

public int getOrder() {

return 0;

}

}(4)测试:注意: 数据库中管理员账户为 : admin , 密码为 : 123456如果不携带token直接访问,则返回401错误如果携带正确的token,则返回查询结果3.3、思考在这一套流程中涉及到了两个微服务:网关微服务和后台管理微服务。而我在对JWT的加解密过程中使用的对称加密算法,这样就会不可避免的导致一个安全隐患:如果有恶意请求利用密钥生成了JWT令牌来进行登录操作,那就会产生不可预知的后果!那要如何避免这个问题呢?我们可以考虑采用非对称算法,生成一个存储着公钥和私钥的密钥库,在生成JWT的时候,使用私钥来进行加密,而解析JWT的服务使用公钥来解析JWT,这样将加密和解析的两把密钥分开来,就可以阻止恶意用户对系统产生恶意攻击了。编辑于 2020-08-06 17:10Spring Cloud网关微服务架构​赞同 51​​8 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录分布式与微服务一名靓仔的架

Spring Cloud Gateway 教程 - spring 中文网

Spring Cloud Gateway 教程 - spring 中文网

spring 中文网

Everything about spring.

菜单

spring 中文网

中文文档

交流论坛

在线留言

关于我们

Spring Cloud Gateway 教程

2023-12-05教程

1、概览

本文将带你了解 Spring Cloud Gateway 的主要功能,它是一个基于 Spring Boot 和 Project Reactor 的网关。

Spring Cloud Gateway 提供开箱即用的路由机制,通常用于微服务应用中,把多个服务隐藏在 “Facade”(门面设计模式)后面。

2、路由处理器

Spring Cloud Gateway 专注于路由请求,它将请求转发给网关 Handler Mapping,由其决定如何处理与特定路由相匹配的请求。

从一个快速示例开始,看看 Gateway Handler 如何使用 RouteLocator 解析路由配置:

@Bean

public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

return builder.routes()

.route("r1", r -> r.host("**.baeldung.com")

.and()

.path("/baeldung")

.uri("http://baeldung.com"))

.route(r -> r.host("**.baeldung.com")

.and()

.path("/myOtherRouting")

.filters(f -> f.prefixPath("/myPrefix"))

.uri("http://othersite.com")

.id("myOtherID"))

.build();

}

注意,有几个核心的 API:

Route - 网关的主要 API。它由给定的标识(ID)、目的地(URI)和一组 Predicate 和 Filter 定义

Predicate - Java 8 Predicate ,用于使用 Header、方法或参数匹配 HTTP 请求

Filter - 标准的 Spring WebFilter

3、动态路由

与 Zuul 一样,Spring Cloud Gateway 也提供了将请求路由到不同服务的方法。

路由配置可以通过纯 Java(如第 2 节中的示例所示,RouteLocator)或属性配置来创建:

spring:

application:

name: gateway-service

cloud:

gateway:

routes:

- id: baeldung

uri: baeldung.com

- id: myOtherRouting

uri: localhost:9999

4、路由工厂

Spring Cloud Gateway 使用 Spring WebFlux HandlerMapping 匹配路由。

它还包括许多内置的 Route Predicate 工厂。所有这些 Predicate 都与 HTTP 请求的不同属性相匹配。多个 Route Predicate 可通过逻辑 “and” 进行组合。

路由匹配既可以通过程序应用,也可以通过配置属性文件使用不同类型的 Route Predicate 工厂应用。

5、WebFilter 工厂

路由过滤器(Route Filter)可以修改传入的 HTTP 请求或传出的 HTTP 响应。

Spring Cloud Gateway 包含许多内置的 WebFilter 工厂,还可以创建自定义 Filter。

6、支持 Spring Cloud DiscoveryClient

Spring Cloud Gateway 可与 Eureka Server 和 Consul 等服务发现和注册中心轻松集成:

@Configuration

@EnableDiscoveryClient

public class GatewayDiscoveryConfiguration {

@Bean

public DiscoveryClientRouteDefinitionLocator

discoveryClientRouteLocator(DiscoveryClient discoveryClient) {

return new DiscoveryClientRouteDefinitionLocator(discoveryClient);

}

}

6.1、LoadBalancerClient Filter

LoadBalancerClientFilter 会使用 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 在 exchange attribute 中查找 URI。

如果 URL 采用 lb scheme(如 lb://baeldung-service),它将使用 Spring Cloud LoadBalancerClient 将名称(如 baeldung-service)解析为实际主机和端口。

未经修改的原始 URL 将被置于 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute 中。

7、监控

Spring Cloud Gateway 使用 Actuator API,这是一个著名的 Spring Boot 库,可为监控应用程序提供多种开箱即用的服务。

一旦安装并配置了 Actuator API,就可以通过访问 /gateway/ 端点来查看网关监控功能。

8、实践

现在,使用 path Predicate 创建一个将 Spring Cloud Gateway 用作代理服务器的简单示例。

8.1、依赖

在 dependencyManagement 中添加当前版本的 spring-cloud-dependencies 依赖:

2022.0.1

org.springframework.cloud

spring-cloud-dependencies

${spring-cloud.version}

pom

import

接下来,添加必要的依赖:

org.springframework.boot

spring-boot-actuator

org.springframework.boot

spring-boot-starter-webflux

org.springframework.cloud

spring-cloud-starter-gateway

8.2、代码实现

在 application.yml 文件中创建一个简单的路由配置:

server:

port: 80

spring:

cloud:

gateway:

routes:

- id: baeldung_route

uri: http://baeldung.com

predicates:

- Path=/baeldung/

management:

endpoints:

web:

exposure:

include: "*"

Application 类:

@SpringBootApplication

public class GatewayApplication {

public static void main(String[] args) {

SpringApplication.run(GatewayApplication.class, args);

}

}

应用启动后,可以访问网址 http://localhost/actuator/gateway/routes/baeldung_route,检查创建的路由配置:

{

"id":"baeldung_route",

"predicates":[{

"name":"Path",

"args":{"_genkey_0":"/baeldung"}

}],

"filters":[],

"uri":"http://baeldung.com",

"order":0

}

如你所见,相对网址 /baeldung 被配置为路由。因此,请求 http://localhost/baeldung/ 后,会被重定向到 http://baeldung.com,正如示例中配置的那样。

9、总结

本文介绍了 Spring Cloud Gateway 的部分功能和组件。

Ref:https://www.baeldung.com/spring-cloud-gateway

spring-cloud-gateway

©️ 版权声明: 未经本站(SPRINGDOC.CN)许可,任何个人或组织严禁转载本站的任何内容。本站拥有所有发布在本站的原创作品的版权。未经许可转载本站内容将被视为侵权行为,本站将采取法律手段维护自身的合法权益。

« 上一篇

Spring Integration 简介

下一篇 »

基于 XML 配置的 Spring AOP 教程

广告

近期文章

在 Spring Boot 中处理 Kafka Offset(偏移量)

使用最新的Mistral AI API,在 Java 和 Spring AI 中进行函数调用

使用 JUnit 和 @DataJpaTest 测试 Spring Data Repository

Spring Data JPA 执行 INSERT 时跳过 SELECT

Spring Data JPA Repository 和数据库视图

分类

教程 

475

新闻 

7

标签

arthas (1)

caffeine (1)

docker (9)

eureka (2)

fastjson (1)

feign (3)

flyway (2)

freemarker (2)

graalvm (3)

gradle (1)

graphql (3)

groovy (1)

gson (2)

h2 (2)

hibernate (4)

httpclient (1)

jackson (4)

java (9)

jooq (5)

jpa (4)

jsp (2)

junit (2)

jwt (4)

kafka (16)

keycloak (7)

kubernetes (1)

log4j2 (3)

maven (2)

minio (1)

mongodb (2)

mybatis (1)

mybatis-plus (1)

mysql (2)

oauth2 (12)

openapi (4)

openfeign (7)

postgres (4)

pulsar (1)

querydsl (2)

react (1)

redis (9)

resilience4j (1)

rsocket (1)

sentinel (1)

shiro (1)

spring (125)

spring-ai (2)

spring-authorization-server (2)

spring-batch (3)

spring-boot (196)

spring-cloud (6)

spring-cloud-aws (2)

spring-cloud-azure (1)

spring-cloud-config (3)

spring-cloud-gateway (9)

spring-cloud-sleuth (1)

spring-cloud-stream (5)

spring-data-jpa (23)

spring-data-redis (3)

spring-integration (1)

spring-jdbc (1)

spring-modulith (3)

spring-native (1)

spring-restdocs (1)

spring-retry (2)

spring-security (47)

spring-statemachine (1)

spring-ws (1)

springdoc (4)

springfox (1)

sqlite (1)

ssl (1)

swagger (9)

thymeleaf (4)

webflux (11)

webfulux (1)

websocket (6)

yaml (1)

zuul (2)

网上邻居

Spring Boot 中文社区

MyBatis Plus

Knife4j

Maven 中文站

Hutool

Jpom 项目运维

投稿 | 隐私政策

|

渝ICP备2023000086号-1

© 2024 springdoc.cn 保留一切权利。

商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

Gateway - 网关 | NOTE

way - 网关 | NOTE

加载中...文章61标签43分类7 首页 归档 标签 分类 友链NOTE 搜索 首页 归档 标签 分类 友链Gateway - 网关发表于2021-02-26|更新于2021-03-01|学习笔记|阅读量:Gateway简介

Gateway官网

Gateway 是在 Spring 生态系统之上构建的 API 网关服务, 基于 Spring5、Springboot2 和 Project Reactor 等技术。

Gateway 旨在提供一种简单而有效的方式来对 API 进行路由, 以及提供些强大的过滤器功能, 例如:熔断、限流、重试等

官网翻译:

SpringCloud Gateway 是 SpringCloud 的一个全新项目, 基于 Spring5.0 + Spring Boot2.0和 Project Reactor 等技术开发的网关, 它旨在为微服务架构提供一种简单有效的统的AP路由管理方式。

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关, 目标是替代 Zuul, 在 Spring Cloud2.0 以上版本中, 没有对新版本的 Zuul2.0 以上最新高性能版本进行集成, 仍然还是使用的 Zuul1.× 非 Reactor 模式的老版本。而为了提升网关的性能, Spring Cloud Gateway 是基于 Webflux 框架实现的, 而 Webflux 框架底层则使用了高性能的 Reactor 模式通信框架Netty。

Spring Cloud Gateway 的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能, 例如:安全、监控/指标和限流。

一句话介绍:Spring Cloud Gateway 使用的 Webflux 中的 reactor-netty 响应式编程组件,底层使用了 Netty 通讯框架

功能

反向代理

鉴权

流量控制

熔断

日志监控

等……

使用位置

和Zuul对比

为什么选择 Gateway?

Netflix 不太靠谱,Zuul2.0 一直跳票, 迟迟不发布

一方面因为 Zuu1.0 已经进入了维护阶段, 而且 Gateway 是 Spring Cloud 团队研发的, 是亲儿子产品, 值得信赖。 而且很多功能 Zuul 都没有用起来也非常的简单便捷。

Gateway 是基于异步非阻塞模型上进行开发的, 性能方面不需要担心。虽然 Netflix 早就发布了最新的 Zuu2.x 但 Spring Cloud 貌似没有整合计划。而且 Netflix 相关组件都宣布进入维护期,不知前景如何?

多方面综合考虑 Gateway 是很理想的网关选择。

SpringCloud Gateway具有如下特性:

基于 Spring Framework 5, Project Reactor 和 Spring Boot2.0 进行构建;

动态路由:能够匹配任何请求属性;

可以对路由指定 Predicate (断言)和 Filter (过滤器);

集成 Hystrix 的断路器功能;

集成 Spring Cloud 服务发现功能;

易于编写的 Predicate (断言)和 Filter (过滤器);

请求限流功能;

支持路径重写。

SpringCloud Gateway与 Zuul 的区别

在 Spring Cloud Finchley 正式版之前, Spring Cloud 推荐的网关是 Netflix 提供的Zuul:

Zuul 1.x 是—个基于阻塞 I/O 的 API Gateway

Zuul 1.x 基 Servlet 2.5 使用阻塞架构它不支持任何长连接如 (Web Socket) Zuul 的设计模式和 Nginx 较像, 每次 I/O 操作都是从工作线程中选择一个执行, 请求线程被阻塞到工作线程完成, 但是差别是 Nginx 用 C++ 实现, Zuul 用 Java 实现, 而 JVM 本身会有第一次加载较慢的情况, 使得 Zuul 的性能相对较差。

Zuul 2.x 理念更先进, 想基于 Neety 非阻塞和支持长连接, 但 Spring Cloud 目前还没有整合。Zuul 2.x 的性能较 Zuul 1.x 有较大提升。在性能方面, 根据官方提供的基准测试, Spring Cloud Gateway 的 RPS (每秒请求数)是 Zuul 的 1.6 倍。

Spring Cloud Gateway 建立在 Spring Framework5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞APl。

Spring Cloud Gateway 还支持 WebSocket, 并且与 Spring 紧密集成拥有更好的开发体验

Zuul1.x模型

Springcloud 中所集成的 Zuul版本, 采用的是 Tomcat 容器, 使用的是传统的 Servlet IO 处理模型。

Servlet 由 Servlet container 进行生命周期管理。container 启动时构造 servlet 对象并调用 servlet init0 进行初始化;container 运行时接受请求, 并为每个请求分配一个线程 (一般从线程池中获取空闲线程) 然后调用 service();container 关闭时调用 servlet destory() 销毁 servlet。

上述模式的缺点:

Servlet 是—个简单的网络 IO 模型, 当请求进入 Servlet container 时, servlet container 就会为其绑定一个线程, 在并发不高的场景下这种模型是适用的。但是一旦高并发(比如抽风用 jmeter 压), 线程数量就会上涨, 而线程资源代价是昂贵的 (上线文切换, 内存消耗大) 严重影响请求的处理时间。

在一些简单业务场景下, 不希望为每个 request 分配个线程, 只需要1个或几个线程就能应对极大并发的请求, 这种业务场景下 Servlet 模型没有优势。

所以 Zuul.x 是基于 Servlet 之上的一个阻塞式处理模型, 即 spring 实现了处理所有 request 请求的一个 servlet( Dispatcher Servlet) 并由该 Servlet 阻塞式处理处理。所以 SpringCloud Zuul 无法摆脱 Servlet 模型这一弊端

Gateway模型

Spring Webflux

传统的 Web 框架, 比如说:struts2, springmvc 等都是基于 Servlet API 与 Servlet 容器基础之上运行的。

但是,

在 Servlet 3.1之后有了异步非阻塞的支持。而 Webflux 是一个典型非阻塞异步的框架, 它的核心是基于 Reactor 的相关API实现的。相对于传统的 web 框架来说, 它可以运行在诸如 Netty, Undertow 及支持 Servlet3.1的容器上。非阻塞式+函数式编程 ( Spring 5 必须让你使用 java 8)。

Spring WebFlux 是 Spring 5.0 引入的新的响应式框架, 区别于 Spring MVC, 它不需要依赖 Servlet API, 它是完全异步非阻塞的, 并且基于 Reactor 来实现响应式流规范。

三大概念Route(路由)

路由是构建网关的基本模块,它由 ID,目标 URI,一系列的断言和过滤器组成,如果断言为 true 则匹配该路由。

Predicate(断言)

参考的是 java 8的java.util.function.Predicate 开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。

Filter(过滤)

指的是 Spring 框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

路由过滤器可用于修改进入的 HTTP 请求和返回的 HTTP 响应, 路由过滤器只能指定路由进行使用。

Spring Cloud Gateway 内置了多种路由过滤器, 他们都由 Gateway Filter 的工厂类来产生。

Spring Cloud Gateway的Filter生命周期

Only Two

pre:在业务逻辑之前

post:在业务逻辑之后

种类

Only Two

GatewayFilter:单一

GlobalFilter:全局

总体而言

web 请求, 通过一些匹配条件, 定位到真正的服务节点。并在这个转发过程的前后, 进行一些精细化控制。

Predicate 就是我们的匹配条件;

Filter, 就可以理解为个无所不能的拦截器;

有了这两个元素, 再加上目标 URL, 就可以实现个具体的路由了。

官网总结

客户端向 Spring Cloud Gateway 发出请求,然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。

Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑, 然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后(post)执行业务逻辑。

Filter 在 pre 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等;在 post 类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流量监控等,有着非常重要的作用。

核心逻辑

路由转发 + 执行过滤器链

代码实现整体代码Pom1234567891011121314151617181920212223242526272829303132333435 org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-netflix-eureka-client com.mrw cloud-api-commons 1.0-SNAPSHOT org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test

Yaml

不暴露8001端口,希望在 8001 外面套一层 9527

动态路由

开启从注册中心动态创建路由的功能,利用微服务名进行路由

cloud.gateway.discovery.locator.enabled=true

断言路径

在网关 Yaml 文件中配置断言路径后,如果该服务提供者接口中的访问路径和断言路径匹配,则进行路由「访问」

1234567891011121314151617181920212223242526272829303132333435363738server: port: 9527spring: application: name: cloud-gateway ##############################为 cloud-payment-service 服务添加断言############################## cloud: gateway: discovery: locator: #开启从注册中心动态创建路由的功能,利用微服务名进行路由 enabled: true routes: - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 #uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/get/** # 断言,路径相匹配的进行路由 - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 #uri: http://localhost:8001 #匹配后提供服务的路由地址 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai] #- Cookie=username,zzyy #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式 #############################################################################################eureka: instance: hostname: cloud-gateway-service client: #服务提供者provider注册进eureka服务列表内 service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka

Main1234567@SpringBootApplication@EnableEurekaClientpublic class GateWayMain9527 { public static void main(String[] args) { SpringApplication.run(GateWayMain9527.class, args); }}

Config

Gateway 网关路由有两种配置:

在 Yaml 配置文件中配置

代码中注入 RouteLocator 的 Bean,如下「通过9527网关访问到外网的百度新闻网址」

12345678910111213@Configurationpublic class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_route_atguigu", r -> r.path("/guonei") .uri("http://news.baidu.com/guonei")).build(); return routes.build(); }}

Filter

自定义全局 GlobalFilter

实现 GlobalFilter 和 Ordered

如下代码

可以用来

全局日志记录

统一网关鉴权

……

带 uname 参数

不带 uname 参数

1234567891011121314151617181920212223242526@Component@Slf4jpublic class MyLogGateWayFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("***********come in MyLogGateWayFilter: " + new Date()); String uname = exchange.getRequest().getQueryParams().getFirst("uname"); if (uname == null) { log.info("*******用户名为null,非法用户,o(╥﹏╥)o"); //设置 Http状态码 exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } //放行 return chain.filter(exchange); } @Override //加载过滤器的顺序,越小优先级越高,一般自定义的全局过滤器都为0 public int getOrder() { return 0; }}

常用Predicate

断言的可配置项

1.After Route Predicate

如下配置的意思:

在2020.02.21 15:51:37之后网关ip:网关port/payment/lb请求才进行路由「访问」

如果访问时间在此之前,会报404错误

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]

如何获取以上的时间戳

12345678910public class TimeZone{ public static void main(String[] args) { ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区 System.out.println(zbj); //2020-02-21T15:51:37.485+08:00[Asia/Shanghai] }}

2.Before Route Predicate

同 After

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Before=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]

3.Between Route Predicate

写两个时间戳,中间逗号隔开,其他同 After

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Between=2020-02-21T15:51:37.485+08:00[Asia/Shanghai],2020-02-21T16:51:37.485+08:00[Asia/Shanghai]

4.Cookie Route Predicate

Cookie route Predicate 需要两个参数

Cookie name

正则表达式

路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配, 如果匹配上就会执行路由, 如果没有匹配上则不执行

如下配置意思

网关ip:网关port/payment/lb请求需要带有 Cookie 且键值对为 username=zhangsan 才会执行路由

否则会报404错误

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Cookie=username,zhangsan # Cookie 键值对

不带 cookie 访问

带上 cookie 访问

5.Header Route Predicate

如下配置的意思:

网关ip:网关port/payment/lb请求头要有X-Request-Id属性并且值为整数才会执行路由

否则会报404错误

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为正整数的正则表达式

带 X-Request-Id 且为正整数

带 X-Request-Id 但不为正整数或不带

6.Host Route Predicate

Host Route Predicate 接收一组参数, 一组匹配的域名列表, 这个模板是一个 ant 分隔的模板, 用 . 号作为分隔符。

它通过参数中的主机地址作为匹配规则。

如下配置的意思:

网关ip:网关port/payment/lb请求头要有Host属性并且值为 xxx.baidu.com 才会执行路由

否则会报404错误

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Host=**.baidu.com

7.Method Route Predicate

请求必须为 Method 指定的请求方式才会执行路由

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Method=GET

8.Path Route Predicate

断言,路径相匹配的进行路由

1234- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由

9.Query Route Predicate

要有参数名为 username 且值为正整数的才会执行路由

12345- id: payment_routh2 uri: lb://CLOUD-PROVIDER-PAYMENT #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 - Query=username,\d+

10.总结

Predicate 就是为了实现一组匹配规则,让请求过来找到对应的 Route 进行处理

文章作者: Mr-Wei文章链接: http://le_xiaobei.gitee.io/2021/02/26/Gateway/版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 NOTE!Gateway上一篇bootstrap下一篇Stream - 消息驱动目录1. Gateway1.1. 简介1.2. 功能1.2.1. 使用位置1.3. 和Zuul对比1.3.1. Zuul1.x模型1.3.2. Gateway模型1.4. 三大概念1.4.1. Route(路由)1.4.2. Predicate(断言)1.4.3. Filter(过滤)1.4.3.1. Spring Cloud Gateway的Filter1.4.3.2. 生命周期1.4.3.3. 种类1.4.4. 总体而言1.4.5. 官网总结1.5. 代码实现1.5.1. 整体代码1.5.1.1. Pom1.5.1.2. Yaml1.5.1.3. Main1.5.1.4. Config1.5.1.5. Filter1.5.1.6. 常用Predicate1.5.1.6.1. 1.After Route Predicate1.5.1.6.2. 2.Before Route Predicate1.5.1.6.3. 3.Between Route Predicate1.5.1.6.4. 4.Cookie Route Predicate1.5.1.6.5. 5.Header Route Predicate1.5.1.6.6. 6.Host Route Predicate1.5.1.6.7. 7.Method Route Predicate1.5.1.6.8. 8.Path Route Predicate1.5.1.6.9. 9.Query Route Predicate1.5.1.6.10. 10.总结 ©2021 By Mr-Wei本