Spring Cloud API Gateway Global Filter Example

This tutorial will teach you how to create a simple Spring Cloud API Gateway Global Pre-filter and Post-filter classes.

Global filters are executed for every route defined in the API Gateway. The main difference between the pre-filter and post-filter classes 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.

For a step-by-step series of video lessons, please check this page: Spring Boot Microservices and Spring Cloud.

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. 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 will 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();

Having access to the HTTP Request object, we can access many of its properties. For example, we can log the Request Path and all HTTP Request Headers.

String requestPath = exchange.getRequest().getPath().toString();
HttpHeaders headers = exchange.getRequest().getHeaders();

Below is an example of a filter() method that logs the value of the Request Path and the name and 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 the 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 the GlobalFilter interface.

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...");
 
}));

I hope this tutorial was helpful to you. If you want to learn more about building RESTful microservices with Spring Boot and Spring Cloud and you like video lessons, please check this page: Spring Boot Microservices and Spring Cloud.

Happy learning! 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *