Mastering Spring Cloud Gateway: Route Metadata, Timeouts, and Discovery Client
This guide explains how to configure route metadata in Spring Cloud Gateway 3.1.4, retrieve metadata via ServerWebExchange, set global and per‑route HTTP timeouts, use Java DSL for timeout settings, and enable DiscoveryClient‑based routing with custom predicates and filters.
Route Metadata Configuration
You can use metadata to configure additional parameters for each route, for example:
spring:
cloud:
gateway:
routes:
- id: route_with_metadata
uri: https://pack.com
metadata:
zone: "xj"
infos:
name: "value"
weight: 0.2All metadata attributes can be obtained from ServerWebExchange:
// Get the route object
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// Get route metadata
route.getMetadata();
// Get a specific metadata entry
route.getMetadata(someKey);The exchange.getAttribute method stores the route object in the current context when the HandlerMapping looks up the route:
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
private final FilteringWebHandler webHandler;
public RoutePredicateHandlerMapping(FilteringWebHandler webHandler, ...) {
this.webHandler = webHandler;
// ...
}
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
// Find route
return lookupRoute(exchange)
.flatMap(r -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
// Save the found route in the execution context
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
})));
}
}HTTP Timeout Configuration
HTTP timeouts (connection and response) can be configured globally and overridden per route.
Global timeout configuration
To configure global HTTP timeout, specify connection timeout in milliseconds and response timeout as a java.time.Duration:
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5sPer‑route timeout configuration
To configure timeout for an individual route, specify the values in the route’s metadata:
- id: per_route_timeouts
uri: https://example.org
predicates:
- name: Path
args:
pattern: /delay/{timeout}
metadata:
response-timeout: 200
connect-timeout: 200Using the Java DSL you can set per‑route timeouts as follows:
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 -> 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();
}Setting a negative timeout disables the global response timeout for that route:
- id: per_route_timeouts
uri: https://example.org
predicates:
- name: Path
args:
pattern: /delay/{timeout}
metadata:
response-timeout: -1Fluent Java routing API
@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("name", "pack"))
.build();
}This style also allows custom predicate assertions. RouteDefinitionLocator beans combine predicates with logical AND, and the fluent API supports and(), or(), and negate() on Predicate classes.
DiscoveryClient Route Definition Locator
You can configure the gateway to create routes based on services registered in a DiscoveryClient‑compatible registry. Enable it by setting spring.cloud.gateway.discovery.locator.enabled=true and ensure a DiscoveryClient implementation (Eureka, Consul, Zookeeper, Nacos) is on the classpath.
By default, routes created from DiscoveryClient use a path predicate defined as /serviceId/** where serviceId is the service name, and a rewrite‑path filter that strips the service ID before forwarding the request.
To customize predicates or filters, set spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y], preserving the default ones if needed. Example:
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 + '/?(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"End of guide.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
