So as you know, the diff between a FORWARD and REDIRECT is that REDIRECT reissues the request and does a round robin outside the DMZ.
A FORWARD uses the saame REQUEST/RESPONSE to loop internally.
However in testing, I noticed that the 'OncePerRequest' filter keeps gets hit over and over when looping a batch call using a FORWARD.
Thats not 'OncePerRequestFilter' ... thats 'PotentiallySeveralDozenTimesPerRequestFilter' :)
I tested this by Using HTTPClient in my integration tests and outputting the request session id when it was hitting the doFilterInternal() method; it was the same request being used (session had NOT been reissued because request had NOT been dropped and recreated... thus same session, same request)
Is this expected functionality?? Or is this a BUG?
Comment From: orubel
I created a workaround for this BTW:
String session
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
if((this.session!=null && request.getSession().getId()==this.session)) {
return true;
}
return false
}
This makes it TRULY a 'OncePerRequest' Filter (almost) :)
Comment From: philwebb
OncePerRequestFilter
is part of Spring Framework so I'll transfer this issue to that team. @orubel Do you have a sample application that demonstrates what you're doing?
Comment From: orubel
You bet. Have a spring-boot starter demoing it : https://github.com/orubel/spring-boot-starter-beapi
The example would be shown through the use of a batch job (as demo'd in the demo-application -> BatchFunctionalTest.groovy)
Request/response call flow is handled through ApiInterceptor and sent to BatchExchangeService where batchresponse() method handles forward (which is called by ApiInterceptor -> postHandle() ):
if(request.getAttribute('batchVars').isEmpty()) {
...
}else{
// concat output
parseBatchOutput(body, request, response, this.responseFileType)
//forward
String path ="/b${this.version}/${this.controller}/${this.action}/**"
def servletCtx = this.ctx.getServletContext()
def rd = servletCtx?.getRequestDispatcher(path)
rd.forward(request,response)
}
Comment From: snicoll
The link above is not valid anymore. If you still have it, please clarify what should be invoked to reproduce the issue.
Comment From: bclozel
I've tried to reproduce this with supported versions and couldn't:
public class TestFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(TestFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
logger.info(request.getRequestURI());
filterChain.doFilter(request, response);
}
}
@RestController
public class TestController {
@GetMapping("/")
public void home(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/test").forward(request, response);
}
@GetMapping("/test")
public String test() {
return "test";
}
}
The request is indeed forwarded but the filter is only called once. We'll reopen if we get a minimal application that reproduces this problem.
Comment From: orubel
You are correct, forgot this was still open. Will not happen if [part of securityFilter
On some of my tests, I had this BEFORE the security filter; might still be an issue but not my issue :)
Can be closed