Spring Cloud Gateway
What is Gateway?
A Gateway is a central entry point that sits between clients(users/apps) and backend services, acting as a traffic controller and security guard for requests Client → Gateway → Backend Services
- Request routing
- Security and access controller
- Traffic management
- Request and response transformation
- Monitoring & logging
Common Gateway
- Spring cloud gateway(this article)
- Kong
- NGINX
- AWS API Gateway
Gateway in microservices architecture
The gateway is almost mandatory because it:
- Hides internal services
- Protects the system
- Simplifes client communication
Spring Cloud Gateway Server WebFlux
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.
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(Coordinate the filter chain). 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.
Configuring Route Predicate Factories and Gateway Filter Factories
Configuring Route Predicate Factories and Gateway Filter Factories
- Shortcut Configuration
- Fully Expanded Arguments
Route Predicate Factories: The Predicate decides whether this request CAN enter the route or not (Route Predicate Factories are defined).
Gateway Filter Factories: Filters decide "what to do" with the request/response AFTER the route has been selected (Gateway Filter Factories are defined).
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
Explanation
- Cookie is a Route Predicate Factory
- mycookie is the cookie name
- mycookievalue is the expected value
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.
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
Explanation
- Cookie is a Route Predicate Factory
- mycookie is the cookie name
- mycookievalue is the expected value
Route Predicate Factories
- Time-based Predicates (Time-based – common for API versioning or schedule-based route activation)
-
After: Matches if the request occurs after a specific datetime.
-
Before: Matches if the request occurs before a specific datetime.
-
Between: Matches if the request occurs between two datetimes (datetime1 and datetime2).
- Header-based Predicates (Header-based – important for authentication and host routing)
-
Cookie: Matches if the request contains a cookie with a name and value that matches a regex.
-
Header: Matches if the request contains a header with a name and value that matches a regex.
-
Host: Matches if the Host header matches an Ant-style pattern (e.g., *.example.com).
- Request Matching Predicates (Detailed request matching – core for path-based routing and query params)
-
Method: Matches if the request uses a specific HTTP method (e.g., GET, POST).
-
Path: Matches if the request path matches a Spring PathMatcher pattern (supports regex and trailing slash).
-
Query: Matches if the request contains a query parameter with a name and optionally a value that matches a regex.
- Remote Address Predicates (IP-based – used for security and access control)
-
RemoteAddr: Matches if the request’s source IP is within a specified CIDR range.
-
XForwardedRemoteAddr: Matches if the X-Forwarded-For header contains an IP within a specified CIDR range (used for proxies).
- Other Important Predicates (Other commonly used predicates)
- Weight: Distributes traffic based on a weight within a route group (used for load balancing).
Gateway Filter Factories
- Header Manipulation Filters (Header operations – very common for customizing requests/responses)
-
AddRequestHeader: Adds a specific header to the request sent to the downstream service.
-
AddResponseHeader: Adds a specific header to the response returned to the client.
-
RemoveRequestHeader: Removes a header from the request before sending it downstream.
-
RemoveResponseHeader: Removes a header from the response before returning it to the client.
-
SetRequestHeader: Replaces the entire value of a header in the request.
-
SetResponseHeader: Replaces the entire value of a header in the response.
- Path and Routing Filters (Routing and path rewriting – essential for API routing)
-
RewritePath: Rewrites the request path using a regular expression (regex).
-
SetPath: Sets a new path for the request using a URI template.
-
StripPrefix: Removes a number of prefix segments from the request path (e.g., remove /api before forwarding to the service).
-
PrefixPath: Adds a prefix to the request path.
- Rate Limiting and Security Filters (Rate limiting and security – important for production)
-
RequestRateLimiter: Limits the request rate (typically using a token bucket with Redis), returns 429 Too Many Requests if exceeded.
-
SecureHeaders: Adds security headers such as X-XSS-Protection, X-Frame-Options, Strict-Transport-Security (HSTS).
-
RequestSize: Limits the size of the request, returns 413 Payload Too Large if exceeded.
-
RequestHeaderSize: Limits the size of request headers.
-
TokenRelay: Forwards the OAuth2 access token from the client to the downstream service (used for authentication).
- Resilience and Error Handling Filters (Error handling and resilience – important for reliability)
-
Retry: Retries a request if it fails (configurable number of retries, backoff, status codes).
-
CircuitBreaker: Applies a circuit breaker (using Resilience4J) to prevent cascading failures, supports fallback.
-
FallbackHeaders: Adds exception details to headers when forwarding to a fallback URI.
- Other Important Filters (Other commonly used filters)
-
PreserveHostHeader: Keeps the original Host header when forwarding the request.
-
SetStatus: Sets the HTTP status code for the response.
-
RedirectTo: Performs an HTTP redirect with a specified status and URL.
-
SaveSession: Saves the session before forwarding the request (used for WebFlux sessions).
Global Filters
Global Filters
- Combined Global Filter and GatewayFilter Ordering
- The Gateway Metrics Filter
- The Local Response Cache Filter
- Forward Routing Filter
- The Netty Routing Filter
- The Netty Write Response Filter
- ReactiveLoadBalancerClientFilter
- RouteToRequestUrl Filter
- The Websocket Routing Filter
- Marking An Exchange As Routed
Combined Global Filter and GatewayFilter Ordering
- Collect all GlobalFilters
- Collect all GatewayFilters for that route
- Combine them into a single filter chain
- Order the filter chain in the order org.springframework.core.Ordered
The following listing configures a filter chain:
@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
The Gateway Metrics Filter
The Gateway Metrics Filter is the default filter in Spring Cloud Gateway used for:
Thu thập số liệu (metrics) cho từng request đi qua Gateway
These metrics are used for:
- System monitoring
- API performance tracking
- Grafana dashboard rendering
- Error/slowdown alerts
You need to add the dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
After adding it, Gateway Metrics Filter will automatically run by default, as long as the following configuration is not set to false.
spring:
cloud:
gateway:
metrics:
enabled: true # default is true
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.
Thanks to these tags you can:
- Identify which routes have the most errors
- Identify which APIs are slow
- Identify which backends frequently return 5xx
The Local Response Cache Filter
LocalResponseCache is a Gateway Filter that caches responses directly in Spring Cloud Gateway, so there is no need for Redis or a distributed cache. It uses Caffeine, a very fast in-memory cache that runs locally in the Gateway’s JVM. Goals:
- Reduce the number of requests sent to the backend
- Improve response time for GET APIs
- Suitable for data that chanes infrequently
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
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 no cache parameters are configured but the global filter is enabled, Spring Cloud Gateway uses a default cache time-to-live (TTL) of 5 minutes for responses.
The filter automatically manages the Cache-Control: max-age header.
If the original response already contains max-age, it is overwritten with the value defined by timeToLive.
For later requests, max-age is recalculated to reflect the remaining time before the cache expires.
Setting spring.cloud.gateway.global-filter.local-response-cache.enabled=false disables response caching for all routes.
Forward Routing Filter, The Netty Routing Filter, The Netty Write Response Filter, ReactiveLoadBalancerClientFilter, RouteToRequestUrl Filter, The Websocket Routing Filter, Marking An Exchange As Routed (content)
HttpHeadersFilters
HttpHeadersFilters
- Forwarded Headers Filter
- RemoveHopByHop Headers Filter
- XForwarded Headers Filter
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. To activate this filter set the spring.cloud.gateway.server.webflux.trusted-proxies property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the Forwarded header.
spring.cloud.gateway.server.webflux.trusted-proxies=10\\.0\\.0\\.5
The Forwarded by header part can be enabled by setting the following property to true (defaults to false): spring.cloud.gateway.server.webflux.forwarded.by.enabled=true
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.server.webflux.filter.remove-hop-by-hop.headers property to the list of header names to remove.
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. To activate this filter set the spring.cloud.gateway.server.webflux.trusted-proxies property to a Java Regular Expression. This regular expression defines the proxies that are trusted when they appear in the Forwarded header. Creating of individual headers can be controlled by the following boolean properties (defaults to true):
- spring.cloud.gateway.server.webflux.x-forwarded.for-enabled
- spring.cloud.gateway.server.webflux.x-forwarded.host-enabled
- spring.cloud.gateway.server.webflux.x-forwarded.port-enabled
- spring.cloud.gateway.server.webflux.x-forwarded.proto-enabled
- spring.cloud.gateway.server.webflux.x-forwarded.prefix-enabled Appending multiple headers can be controlled by the following boolean properties (defaults to true):
- spring.cloud.gateway.server.webflux.x-forwarded.for-append
- spring.cloud.gateway.server.webflux.x-forwarded.host-append
- spring.cloud.gateway.server.webflux.x-forwarded.port-append
- spring.cloud.gateway.server.webflux.x-forwarded.proto-append
- spring.cloud.gateway.server.webflux.x-forwarded.prefix-append
CORS Configuration
Global CORS Configuration
CORS The “global” CORS configuration is a map of URL patterns to Spring Framework CorsConfiguration. The following example configures CORS
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://docs.spring.io"
allowedMethods:
- GET
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
Route CORS Configuration
The “route” configuration allows applying CORS directly to a route as metadata with key cors.
spring:
cloud:
gateway:
routes:
- id: cors_route
uri: https://example.org
predicates:
- Path=/service/**
metadata:
cors:
allowedOrigins: '*'
allowedMethods:
- GET
- POST
allowedHeaders: '*'
maxAge: 30
Link to video tutorial on building an API gateway
All Rights Reserved