I'm coming from Node-ExpressJS, so I am familiar with the concept of middlewares. As I was learning Spring, I came to know of a component called Filter
which pretty much acts like middlewares in Express with a few differences.
So I'm trying to understand how a Filter
and FilterChain
actually works in Spring.
I have the following code:
Filter1.java
@Component
@Order(1)
public class Filter1 implements Filter {
.....
.....
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("############# Invoking Filter1 ############");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
LOGGER.info("************ Moving on to next Filter");
LOGGER.info("Adding new Attribute");
req.setAttribute("Custom_Attribute_1", "TEST***TEST***TEST");
chain.doFilter(request, response);
resp.addHeader("1st Header", "1ST"); // Custom header that never shows up
LOGGER.info("+++++++++ GOING BACK FROM Filter1 +++++++++");
}
}
Filter2.java
@Component
@Order(2)
public class Filter2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
LOGGER.info("############# Invoking Filter2 ####################");
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
req.setAttribute("Filter2 Attribute", "2nd ORDER");
resp.addHeader("2nd Header", "2ND"); //Custom header that actually shows up
chain.doFilter(request, response);
LOGGER.info("+++++++++++ GOING BACK FROM Filter2 ++++++++++");
}
}
Controller.java
@RestController
public class Controller {
@GetMapping("/")
public ResponseEntity<Object> createResource(HttpServletRequest req) {
return new ResponseEntity<Object>("Resource Created",HttpStatus.OK);
}
}
When I send a request to my controller using Postman, I can see only one of my custom headers in the response, namely the 2nd Header
, but can't see the other header.
Headers of response in Postman
2nd Header → 2ND
Content-Type → text/plain;charset=UTF-8
Content-Length → 15
Date → Thu, 19 Sep 2019 20:16:25 GMT
Does the call of chain.doFilter(request, response)
have anything to do with it? It seems like there can be no modification to the response
object in Filter1
class once doFilter
of FilterChain
has been called.
What I am trying to understand here is:
If
FilterChain.doFilter
is what needs to be called to propagate therequest
object to the next filters and eventually to the controller, shouldn't theresponse
object be allowed to be modified once the call tochain.doFilter
returns? How exactly does it work internally? How does the call propagate all the down to the controller and then come back up to the first filter?Also, if Filter1 wanted to see the body of the response after it returned from Filter2 and possibly modify it, how would it do so?