Attention Tomcat developers who know how the Coyote bit of Tomcat works… I’ve got a tricky one for you! :-)
We’re struggling with a puzzling problem where intermittently, calls to a servlet are delivered back to the client with all of the headers missing except the ones that Coyote adds. In roughly 9,999 out of 10,000 attempts the response returns correctly (which includes a number of headers which are added by filters, a body response which is gzipped by the servlet and a “Content-Encoding” header which indicates it’s gzipped, and the correct “Content-Length” header). But, intermittently, approximately 1 time out of 10,000 requests, the response back to the client contains only 3 headers: “Date”, “Server”, and a “Transfer-Encoding” header set to “chunked” (even though the response body is not chunked). The result of this is that the gzipped body is presented back to the client with the “Content-Encoding” header missing so it’s rendered unreadable by the browser, and all of the other headers are missing. (We’ve determined this by being able to capture a couple of instances of this issue in Fiddler). Looking at the Coyote source code it would appear that if the “Content-Length” header isn’t presented to Coyote from the upstream handling of the filters and servlet then it’ll default to a chunked encoding, which explains why the response is getting chunked! So, basically - the filters run without error, the servlet runs without error, but the when the response is received back into Coyote’s AbstractHttp11Processor.process() method, the headers have disappeared! Annoyingly we can’t find a recreatable test case, but anecdotally it’s when the server is heavily loaded, but there are still plenty of pooled workers available, and plenty of memory. This is a very high volume server (probably millions of requests a day) so adding verbose logging within Coyote isn’t a realistic option. I don’t believe it’s actually possible for the filters or the servlet to remove headers even if they want to (they don’t appear to have any access to the MimeHeaders of the Coyote “Response” object, and the HttpServletResponse object doesn’t have any methods which allow header removal). The only clue we have is occasionally we see “INFO: Encountered a non-recycled response and recycled it forcedly.” in the logs, but these errors are infrequent compared to the number of instances of the problem, and the timestamps of these errors don’t correspond to when users have reported the error. My best guess would be somehow the Coyote “Request” object is accidentally accessed by two threads concurrently to service two requests, and one request is calling the Request.recycle() (which is calling headers.recycle() which removes all of the headers) but I’m struggling to see how that could happen. Note we are not using async servlets. I appreciate 7.0.72 isn’t the very latest and greatest version but I can’t find anything in the change log for later 7.x, 8.x, 8.5.x or 9.x releases which indicate this is a known issue or resolved. Any ideas about how to further diagnose this would be very gratefully received. Otherwise our next step is to blindly update to later versions and just hope it goes away. Thanks, Richard