Spring Cloud Gateway || Modify Response Body Using Post Global Filter

Shubham Wankhede
5 min readApr 13, 2022

--

modify response body of route in spring cloud gateway

Hi everyone, have you ever worked with Filters ? if yes, then you know how easy it is to modify the response body through filters, but is it the same when we are working with Spring Cloud Gateway šŸ¤” ?

What? whatā€™s so special about Spring Cloud gateway is it not how we normally work with other filters ? well, yes, it is both easy and difficult to work with Spring Cloud Gateway filters because unlike other cases we need to work with Spring Webflux i.e Spring React when we are working with Spring Cloud Gateway and itā€™s filters. So, if you donā€™t know about spring react then it can be somewhat changing to work with them and also we need to configure filters for specific route differently and Global filter (which will be applicable for all routes) differently.

In this blog we will understand about how to modify response body using post global filter, letā€™s understand this with an example.

For this blog example Iā€™ll be creating two applications, one is our Gateway Application and other is a normal Demo Application (i.e. Restful Application)

To create a Gateway Application Iā€™ve used the Spring Initializr with below configuration

and for Demo Application i.e Restful Application Iā€™ve used the below spring initializr configuration.

once we are done with creating the applications letā€™s configure themand run them.

Spring Cloud Gateway

we will be running the spring cloud gateway on 8080 port along with few configurations to route the incoming request to Demo Applicationā€™s available endpoints.

all the incoming request whose path is starting with /api/** example: http://localhost:8080/api/v1/print will be routed to specified uri i.e. to http://localhost:8081 on which our Demo Application is running.

Demo Application (Restfull Application)

In Demo Application which is a Restful Application we have one RestController class which contains one endpoint with url mapping as /print this endpoint just return the ā€œSuccessā€ String whenever we call it and incase the passed parameter String is ā€œbadRequestā€ it return ā€œbad requestā€ as request body and 400 response status code.

this application is running on 8081 port.

Now letā€™s test the endpoints to check the desired results before we modify the response.

Test 01: with param value as ā€œreqā€ i.e testParam = req

Expected result šŸ˜Ž.

Test 02: with param value as ā€œbadRequestā€ i.e testParam=badRequest

resultā€™s are as expected šŸ˜Ž for both the cases before modifying the response.

Global Post Filter to Modify Response Body for Bad Request Response Status

now letā€™s see how to create a Global post filter to modify the response body whenever route returns the 400 error status code.

But first what should we modify it with ?

letā€™s do this whenever the routes response status is 400 we will just change the response body to below html page.

<body>
<h1 style="color:red;text-align:center">Bad Request </h1>
<p>If you are seeing this page it means response body is
modified.</p>
</body>

to achieve this we are creating one java class as below and implementing that class with GlobalFilter interface and Ordered Interface and overriding their respective methods to provide the filter logic and filter execution order.

for simplicity purpose Iā€™m taking Html code as a String instead of reading it from the file.

Before we go any further let me explain you the code

we are checking the response status obtained from the route of Demo Application and comparing if it is 400 or not, if it is a 400 error status then we are writing the html code as bytes to data buffer and publishing this buffer data to response by wrapping it, lastly we are mutating the ServerWebExchange object with modified response.

lastly donā€™t forget to register this filter class as Spring Bean by returning its object from the @Bean annotated method from Configuration class as below.

@Bean
public GlobalFilter responseFilter(){
return new PostGlobalFilter();
}

letā€™s test the scenarios after we write filter to modify response.

Test 01: with testParam = req

Yep, expected result šŸ˜Ž.

Test 02: with testParam = badRequest

what ? old result šŸ˜³ ? what happened ? this is not what I was expecting .

well the reason you are not getting the desired result is because once you publish the content to response you need to subscribe to it as below.

response.writeWith(Mono.just(dataBuffer)).subscribe();

if you just add subscribe() method to writeWith() method you are good to go.

Now letā€™s test again after correcting the above line.

Blank Screen ? Not again šŸ˜«šŸ˜«šŸ˜« why are you punishing me god šŸ˜œšŸ˜œ
what happened now šŸ„²?

if you look at the response through Network tab in inspect element of browser carefully you will find that partial response is coming as a response body

always remember that whenever you are modifying the response always modify the response content length according to new response body.

response.getHeaders().setContentLength(newResponseBody.length());

Now letā€™s try again

Yes ! Yes ! Now this world shall be under my feet šŸ˜Ž !

Just kidding šŸ˜œ

the final version of filter method is as below.

it was fun thought, I hope you enjoyed the blog.

--

--