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

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.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store