Spring Cloud Gateway Pre and Post Global Filter || Global Request And Response Filter
Hi everyone, if you are working with spring cloud gateway then you might have come across the use of global filters either to read JWT token or modify add some request headers or might be for some other reason, so let’s understand the global filters in Spring Cloud Gateway with a simple example.
to understand global filters in spring cloud gateway I’m create two simple spring boot application, one is acting as a gateway i.e. spring cloud gateway and other is a normal rest services which will going to access it through our gateway.
For Gateway I’ve created application using spring initializr with below configurations.
and for Rest service which we are calling through gateway is as given below.
after creating these project follow the below configurations and class creating which is required for our example.
Gateway
In gateway rename application.properties as application.yaml (optional) and write the below configuration, you can choose any port number to run you gateway Im choosing 8080 port here for gateway
as you can see in above configuration I’ve configured the routes and in there all the request coming to gateway is routed to uri specified in the predicate i.e all the request coming path which contains /api/** (ex. http://localhost:8080/api/v1/print )is redirected to specified uri i.e to http://localhost:8081
so far the only responsibility of the gateway is to redirect the request coming to specified route uri
Rest Service
In rest service which is a independent service we are having a one rest endpoint which is a public endpoint inside the DemoRestController.java class which is RestController class
Now we are ready with our basic setup i.e. one Rest Service and a Gateway although the Rest Service is exposed publicly we are routing it there through Gateway for our example.
Pre Global Filter ( Request Filter )
there are few ways by which we can create global filter in spring cloud gateway i.e. creating a @Bean method which returns the GlobalFilter and writing the anonymous inner class of GlobalFilter interface as a return value.
second approach is to create a dedicated java class and implement the GlobalFilter interface for that class and override the GlobalFilter interface filter method inside that class and lastly to configure that class as a Spring bean by returning that class object through @Bean method.
here you will observe that I’ve also implemented this class with Ordered interface to provide the execution order for this filter, remember the lower the order the higher the priority it has.
also you need to remember to make this class as Spring bean class by returning it from the @Bean method inside the Configuration class(@SpringBootApplication or @Configuration annotated class).
@Bean
public GlobalFilter requestFilter(){
return new GlobalRequestFilter();
}
the logic for this filter is simple, the request is passing one request parameter along with it and filter is just checking if the request param value is matching with String “throwException” and if it is matching then filter is throwing an exception without routing it to the rest service otherwise if the request parameter value is anything other than ‘throwException’ then request is routed to Rest Service and return “Success”.
let’s test it to see if it works.
Test 01 : for the first case where we pass param value as “throwException” i.e testParam = throwException
it is throwing an exception as we have written in filter which is an expected behaviour 😎.
2. check for positive result case i.e. value of request param other than “throwException” i.e testParam = ex.
Working as expected for param other than throwException.
Post Global Filter (Response Filter)
Post global filters are usually used in spring cloud gateway to perform operations on response like adding some headers or modifying response body or response status etc. let’s see response manipulation with an example to modify the response status code from 200 to 201.
the process for creating a Post global filter is same as that of the Pre filter just that we need to process the request after it send response from its route as follows below
here you can see that once the request is completed then I’m processing the response.
Don’t forget to configure this class as a Spring bean.
@Bean
public GlobalFilter resFilter(){
return new GlobalResponseFilter();
}
Now let’s check if it is working or not, before that remember that in Rest Service endpoint i.e. /api/v1/print we are returning “Success” as a response body and HttpStatus.OK (200) as a response status and in Post filter what we are trying to achieve is to modify the response status from 200 to 201.
here you can see that even through the response status send by endpoint is 200 but what we are getting in actual response is 201 because status is being modified by Post Filter to make it as 201, like this you can modify the other response parameters if you want.
Pre and Post Filter using lambdas in @Bean Method
as you have seen that to write Pre and Post Global filter we have to write the separate java classes but is there a way to write pre and post filter logic without creating a separate classes ?
yes there is, since GlobalFilter interface is an interface which has only one abstract method i.e. it acts as a Functional Interface, so instead of creating a class and implementing the class with GlobalFilter Interface we can directly write the logic as a lambda expression and return it through @Bean method.
here to replace Ordered interface we are using the @Order annotation which works the same way as Ordered interface to provide the filter execution order.
going even further if you want to write the request and response processing logic inside the same method instead of creating two different once for pre and post, you can write just one by writing request processing logic before returning the value and response processing logic in then() method as below.
see my other blog to understand how to modify response body and what all things you need remember while overriding the response body.