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. Multiple Route Predicate Factories can be combined and are combined via logical and
.
The After
Route Predicate Factory takes one parameter, a datetime
(which is a java ZonedDateTime
). This predicate matches requests that happen after the current datetime.
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 after Jan 20, 2017 17:42 Mountain Time (Denver).
The Before
Route Predicate Factory takes one parameter, a datetime(which is a java ZonedDateTime
). This predicate matches requests that happen before the current datetime.
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 before Jan 20, 2017 17:42 Mountain Time (Denver).
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.
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 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.
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 the value matches the regular expression.
application.yml.
spring: cloud: gateway: routes: - id: cookie_route uri: https://example.org predicates: - Cookie=chocolate, ch.p
This route matches the request has a cookie named chocolate
who’s value matches the ch.p
regular expression.
The Header
Route Predicate Factory takes two parameters, the header name
and a regexp
(which is a Java regular expression). This predicate matches with a header that has the given name and the value matches the regular expression.
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
whos value matches the \d+
regular expression (has a value of one or more digits).
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.
application.yml.
spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Host=**.somehost.org,**.anotherhost.org
URI template variables are supported as well, such as {sub}.myhost.org
.
This route would match if the request has a Host
header has the value www.somehost.org
or beta.somehost.org
or www.anotherhost.org
.
This predicate extracts the URI template variables (like sub
defined in the example above) 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
The Method
Route Predicate Factory takes a methods
argument which is one or more HTTP methods to match.
application.yml.
spring: cloud: gateway: routes: - id: method_route uri: https://example.org predicates: - Method=GET,POST
This route would match if the request method was a GET
or a POST
.
The Path
Route Predicate Factory takes two parameter: a list of Spring PathMatcher
patterns
and an optional flag to matchOptionalTrailingSeparator
.
application.yml.
spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Path=/foo/{segment},/bar/{segment}
This route would match if the request path was, for example: /foo/1
or /foo/bar
or /bar/baz
.
This predicate extracts the URI template variables (like segment
defined in the example above) 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 is available to make access to these variables easier.
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
The Query
Route Predicate Factory takes two parameters: a required param
and an optional regexp
(which is a Java regular expression).
application.yml.
spring: cloud: gateway: routes: - id: query_route uri: https://example.org predicates: - Query=baz
This route would match if the request contained a baz
query parameter.
application.yml.
spring: cloud: gateway: routes: - id: query_route uri: https://example.org predicates: - Query=foo, ba.
This route would match if the request contained a foo
query parameter whose value matched the ba.
regexp, so bar
and baz
would match.
The RemoteAddr
Route Predicate Factory takes a list (min size 1) of sources
, which are CIDR-notation (IPv4 or IPv6) strings, e.g. 192.168.0.1/16
(where 192.168.0.1
is an IP address and 16
is a subnet mask).
application.yml.
spring: cloud: gateway: routes: - id: remoteaddr_route uri: https://example.org predicates: - RemoteAddr=192.168.1.1/24
This route would match if the remote address of the request was, for example, 192.168.1.10
.
The Weight
Route Predicate Factory takes two arguments group
and weight
(an int). The weights are calculated per group.
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 https://weighthigh.org and ~20% of traffic to https://weighlow.org
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 which 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
which 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 which correlates to the number of trusted infrastructure running in front of Spring Cloud Gateway.
If Spring Cloud Gateway is, for example only accessible via 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.
Given the following header value:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
The maxTrustedIndex
values below will yield the following remote addresses.
maxTrustedIndex | result |
---|---|
[ | (invalid, |
1 | 0.0.0.3 |
2 | 0.0.0.2 |
3 | 0.0.0.1 |
[4, | 0.0.0.1 |
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") )