Spring Cloud Gateway: Basic Example
Source: Dev.to

Spring Cloud Gateway (also known as a gateway or Edge Service) is a dynamic routing server. In other words, it allows us to have a centralized access point to our microservices. Additionally, we can extend its functionality by adding filters or predicates, among other things.
1. Spring Cloud Gateway Configuration
Create a project using Spring Initializr (or your favorite IDE) and make sure to select the following dependencies:
- Eureka Discovery Client
- Gateway
The project will also be registered by Eureka Server, so add the following configuration:
@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
Application properties (YAML)
spring:
application:
name: gateway-server-service
server:
port: 8090
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
2. Routes
The minimum essential configuration for the Edge/Gateway is the routes. These routes redirect requests from the gateway to the service that will answer the request.
Basic route configuration (YAML)
spring:
cloud:
gateway:
routes:
- id: employees
uri: lb://employees
predicates:
- Path=/api/employees/**
filters:
- StripPrefix=2
Explanation
| Element | Description |
|---|---|
id | Unique identifier of the route. |
uri | Address where the gateway will look for the service to redirect. It must start with lb (Load Balancer) when using service discovery like Eureka. |
predicates | Rules that must be met for the redirection. |
filters | Operations that manipulate the request/response passing through the declared route. |
In the example above, the gateway routes to a microservice called employees. To get a response from it, you call the Spring Cloud Gateway on the gateway’s port (8090) instead of the microservice’s port directly.
2.1 Predicates
Predicates are a list of rules that must be satisfied for the redirection to succeed. They can be based on path, header, HTTP method, query parameter, or cookie.
Examples
predicates:
- Path=/api/products/**
- Header=token, \d+
- Method=GET, POST
- Query=color
- Cookie=color, blue
Meaning
| Predicate | Description |
|---|---|
Path | Redirects requests that match the declared path. |
Header | Checks that the specified header is present with a value that matches the given regular expression. |
Method | Allows only the listed HTTP methods. |
Query | Requires the given query parameter to be present in the URL. |
Cookie | Checks that the specified cookie exists (and optionally matches a value). |
2.2 Spring Cloud Gateway Factory Filters
Factory filters let you manipulate the request and response (e.g., add headers or request parameters).
Configuration (YAML)
filters:
- AddRequestHeader=token-request, 123456
- AddResponseHeader=token-response, 12345678
- SetResponseHeader=Content-Type, text/plain
- AddRequestParameter=name, andres
These filters are applied only to the route where they are declared.
2.3 Spring Cloud Gateway Global Filters
Global filters are applied to all requests passing through the gateway, without needing to declare them per‑route.
Example implementation
package com.funcionaenmimaquina.springboot.app.gateway.filters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class ExampleGlobalFilter implements GlobalFilter, Ordered {
private final Logger logger = LoggerFactory.getLogger(ExampleGlobalFilter.class);
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("Executing request filter");
// Modifying the request
exchange.getRequest()
.mutate()
.header("environment", "dev")
.build();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
logger.info("Executing response filter");
// Adding a cookie to the response
exchange.getResponse()
.addCookie(ResponseCookie.from("myCookie", "myValue")
.path("/")
.maxAge(3600)
.build());
}));
}
@Override
public int getOrder() {
// Lower values have higher precedence
return -1;
}
}
In this example, the filter adds an environment header to every incoming request and a cookie named myCookie to every response.
Global Filter Example (continued)
o("Executing response filter");
// Modifying the response
Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("environment"))
.ifPresent(value -> {
exchange.getResponse().getHeaders().add("env", value);
});
exchange.getResponse().getHeaders().setContentType(MediaType.TEXT_PLAIN);
}))
;
@Override
public int getOrder() {
return 1;
}
}
How the example works
- Implements the
GlobalFilterandOrderedinterfaces. getOrderdefines the execution order when multiple global filters are present.- The
filtermethod contains all logic that interacts with the request and response. - Line 24 shows where you can manipulate the request (e.g., adding a header).
- Line 27 shows how to manipulate the response using
.then(Mono.fromRunnable(...)). - Line 31 adds a header to the response if a specific request header exists.
- Line 34 forces the response to use plain‑text (
text/plain) media type.
2.4 Filter Factory (Custom Gateway Filter)
If you want a filter to apply only to selected routes, create a custom filter factory:
@Component
public class ExampleGatewayFilterFactory
extends AbstractGatewayFilterFactory {
private final Logger logger = LoggerFactory.getLogger(ExampleGatewayFilterFactory.class);
public ExampleGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
logger.info("Zone to modify the request");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
logger.info("Zone to modify the response");
Optional.ofNullable(config.cookieValue).ifPresent(cookieVal -> {
exchange.getResponse()
.addCookie(ResponseCookie.from(config.cookieName, cookieVal).build());
});
}));
};
}
@Override
public String name() {
return "ExampleCookie";
}
@Override
public List shortcutFieldOrder() {
return Arrays.asList("cookieName", "cookieValue");
}
public static class Config {
private String cookieName;
private String cookieValue;
// Getters and Setters
public String getCookieValue() { return cookieValue; }
public void setCookieValue(String cookieValue) { this.cookieValue = cookieValue; }
public String getCookieName() { return cookieName; }
public void setCookieName(String cookieName) { this.cookieName = cookieName; }
}
}
Usage in application.yml
filters:
- StripPrefix=2
- ExampleCookie=user, myName
What the code does
- Adds a cookie to the response using the values defined in the YAML file.
Conventions & requirements
- The class name must end with
FilterFactory. - It extends
AbstractGatewayFilterFactory. - An inner
Configclass stores values supplied from the YAML file. - The filter logic resides in the
applymethod. - The
name()method’s return value must match the key used in the YAML (or default to the class‑name prefix). shortcutFieldOrderdefines the order in which the short‑notation values are mapped to the configuration fields.
Only the routes that reference this filter in application.yml will have it applied.
Conclusions
You now understand:
- What Spring Cloud Gateway is and the problems it solves.
- How to configure predicates and filters to extend its functionality.
- How to create global filters and custom filter factories for fine‑grained control.
Practice building and customizing gateways to become comfortable using them in real‑world projects.
