Core Components of Spring Cloud Gateway
- Route: The fundamental building block of the gateway, consisting of an identifier, destination URI, predicates, and filters. When a request reaches the gateway, the Gateway Handler Mapping evaluates routes based on predicates. When a predicate returns true, the corresponding route is selected for forwarding.
- Predicate: Enables developers to match elements within HTTP requests. Once a predicate evaluates to true, the appropriate route is selected for forwarding.
- Filter: Allows for business logic processing before and after request transmission, such as authentication, monitoring, rate limiting, and more.
The overall operational flow is as follows: Predicates act as matching conditions, while filters functon as versatile interceptors. Together with the target URI, they form a complete routing mechanism.
When a client makes a request to Spring Cloud Gateway, if the request matches a defined route, it's sent to the gateway's Web handler. The handler then executes a specific filter chain. Filters are separated by dashed lines because they may execute logic before and after the proxy request. All pre-filter logic runs first, followed by the proxy request, and finally, the post-filter logic executes after the proxy request completes.
Filter Categories
- GlobalFilter
- RouteFilter
AddRequestParameter GatewayFilter Factory
This filter adds specified parammeters to the request. The configuration AddRequestParameter=param, blue adds a parameter with key "param" and value "blue". The first path segment "gateway" is stripped.
spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
- id: add_request_parameter_route
predicates:
- Path=/gateway/**
uri: http://localhost:8082/
filters:
- StripPrefix=1
- AddRequestParameter=param, blue
RequestRateLimiter GatewayFilter Factory
This filter implements rate limiting for all requests reaching the gateway. When rate limiting is applied, it responds with HTTP 429 - Too Many Requests by default. RequestRateLimiterGatewayFilterFactory provides RedisRateLimiter implementation, which uses the token bucket algorithm for rate limiting.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
@Component
public class ClientAddressKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
spring:
cloud:
gateway:
routes:
- id: rate_limiter_route
predicates:
- Path=/rate_limit/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
deny-empty-key: true
keyResolver: '#{@clientAddressKeyResolver}'
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 2
uri: lb://order-service
The redis-rate-limiter filter has two configuration properties that align with the token bucket concept:
- replenishRate: The rate at which tokens are added to the bucket, representing the number of requests allowed per second.
- burstCapacity: The maximum capacity of the token bucket, representing the maximum number of requests a user can make per second.
Retry GatewayFilter Factory
This filter enables request retry mechanisms when backend services are unavailable. The gateway initiates retry requests based on configured parameters.
spring:
cloud:
gateway:
routes:
- id: retry_route
uri: http://www.example.com
predicates:
- Path=/example/**
filters:
- name: Retry
args:
retries: 3
status: 503
- StripPrefix=1
RetryGatewayFilter provides four parameters to control retry behavior:
- retries: Number of retry attempts, default is 3.
- status: HTTP status codes that trigger retries. Multiple status codes can be specified. In the example above, retries occur when the server returns status 503.
- methods: Specifies HTTP methods that should be retried, default is GET.
- series: Configures error code ranges for retries. Default is SERVER_ERROR(5), meaning all 5xx status codes trigger retries. If series is configured but status is not, it will still match based on series for retries.
Custom Predicate Implementation
To create custom predicates, extend the AbstractRoutePredicateFactory class:
@Component
public class AuthorizationRoutePredicateFactory extends AbstractRoutePredicateFactory<AuthorizationRoutePredicateFactory.Config> {
public AuthorizationRoutePredicateFactory() {
super(Config.class);
}
private static final String HEADER_NAME_KEY = "headerName";
private static final String HEADER_VALUE_KEY = "headerValue";
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(HEADER_NAME_KEY, HEADER_VALUE_KEY);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
// Checks if the request header contains a specific value
return exchange -> {
HttpHeaders headers = exchange.getRequest().getHeaders();
List<String> headerValues = headers.get(config.getHeaderName());
return headerValues != null && !headerValues.isEmpty();
};
}
public static class Config {
private String headerName;
private String headerValue;
public String getHeaderName() {
return headerName;
}
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
public String getHeaderValue() {
return headerValue;
}
public void setHeaderValue(String headerValue) {
this.headerValue = headerValue;
}
}
}
spring:
cloud:
gateway:
routes:
- id: authorization_route
predicates:
- Authorization=Authorization,token
filters:
- StripPrefix=1
uri: https://www.example.com
Custom Filter Implementation
To create custom filters, extend the AbstractGatewayFilterFactory class:
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.CustomConfig> {
private static final String PARAM_NAME_KEY = "paramName";
private final Logger logger = LoggerFactory.getLogger(CustomGatewayFilterFactory.class);
public CustomGatewayFilterFactory() {
super(CustomConfig.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(PARAM_NAME_KEY);
}
@Override
public GatewayFilter apply(CustomConfig config) {
// Filter with pre and post phases
return (exchange, chain) -> {
logger.info("[Pre-filter] Processing request, parameter: " + config.getParamName());
// Custom pre-processing logic
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// Custom post-processing logic
logger.info("[Post-filter] Processing response");
}));
};
}
public static class CustomConfig {
private String paramName;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
}
}
spring:
cloud:
gateway:
routes:
- id: custom_route
predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
- Custom=Hello world
uri: http://localhost:8082/
Gateway Configuration Verification
To view the gateway's route configuration, access the following endpoint:
http://ip:port/actuator/gateway/routes