
Global filters are executed for every route defined in the API Gateway. The main difference between pre-filter and post-filter class is that the pre-filter code is executed before Spring Cloud API Gateway routes the request to a destination web service endpoint. While the post-filter code will be executed after Spring Cloud API Gateway has routed the HTTP request to a destination web service endpoint.
Let’s create a global pre-filter class first.
Creating a Global Pre-Filter Class
To create a global pre-filter we will need to create a new Java class that implements the GlobalFilter interface.
@Component
public class MyPreFilter implements GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// Filter code here
return chain.filter(exchange);
}
}
Notice that this class is annotated with the @Component annotation. This is needed to make the Spring Framework notice this filter class, create its instance, and place it in the Application context.
The code example above is the basic implementation of the custom global pre-filter in Spring Cloud API Gateway. It takes in the ServerWebExchange object from which we can read the details of the HTTP request. If needed, we can add new details to this HTTP request and then pass the ServerWebExchange object to the next filter in the chain. Once all pre-filters in the filter chain are executed, Spring Cloud API Gateway fill route the request to a destination microservice.
To see if this filter is executed, I can make it log a simple message. Below is a code example of a global pre-filter that simply logs a message when this filter is executed.
@Component
public class MyPreFilter implements GlobalFilter {
final Logger logger = LoggerFactory.getLogger(MyPreFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("Pre Filter executed");
return chain.filter(exchange);
}
}
Accessing HTTP Request Details
The Global Filter class can access current HTTP Request details and if needed add additional details. To access HTTP Request details we will use the ServerWebExchange object.
ServerHttpRequest httpRequest = exchange.getRequest();
Below is an example of a filter() method that logs the value of Request Path, as well as a name and a value of each HTTP Request header.
@Component
public class MyPreFilter implements GlobalFilter {
final Logger logger = LoggerFactory.getLogger(MyPreFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("Pre-Filter executed");
String requestPath = exchange.getRequest().getPath().toString();
logger.info("Request path = " + requestPath);
HttpHeaders headers = exchange.getRequest().getHeaders();
Set<String> headerNames = headers.keySet();
headerNames.forEach((header) -> {
logger.info(header + " " + headers.get(header));
});
return chain.filter(exchange);
}
}
Creating a Global Post-Filter Class
Global post-filter classes are executed after Spring Cloud API Gateway routes a request to destination service. There are different ways how to create filters in Spring Cloud API Gateway. In the below code example, I will create a post-filter as a separate class that implements GlobalFilter interface.
The code example above is the basic implementation of the custom global pos-filter in Spring Cloud API Gateway.
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyPostFilter implements GlobalFilter {
final Logger logger = LoggerFactory.getLogger(MyPostFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.fromRunnable(()-> {
logger.info("Global Post-filter executed...");
}));
}
}
Notice that for the pre-filter code we still need to pass execution to the next filter in the chain. This is done by calling the chain.filter(exchange) function. But then, after the filter chain completes, we run a new Mono instance to execute our pre-filter code.
return chain.filter(exchange).then(Mono.fromRunnable(()-> {
logger.info("Global Post-filter executed...");
}));
Conclusion:
In conclusion, API Gateway is an important design concept. With an increasing number of microservices, In this tutorial, we will learn how to create a simple Spring Cloud API Gateway Global Pre-filter and Post filter.
