Spring Cloud Gateway || Modify Response Body Using Post Global Filter
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.