Spring-framework: InputStream consumed by DispatcherServlet logRequest

Created on 10 Dec 2019  路  9Comments  路  Source: spring-projects/spring-framework

Affects: 5.2.1


A few weeks ago I enabled debug logging for my application, today I had forgotten about but noticed that my injected InputStream was empty. After a debugging session (first assuming it again was related to the HiddenHttpMethodFilter) I ended up at

https://github.com/spring-projects/spring-framework/blob/8d846500eff3e51fc49846a969ae1a7f4671015d/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java#L955-L965

So every time I enable debug logging I cannot use my injected InputStream:

@PostMapping
public ResponseEntity<String> doPost(InputStream input, HttpServletRequest request) {
    ...

I do now get this logging:

2019-12-10T10:27:46,305 [http-nio-8082-exec-7] DEBUG org.springframework.web.servlet.DispatcherServlet - POST "/communication", parameters={masked}

But maybe it would make sense to auto-wrap the request in DEBUG when that logging is active or give a warning when injecting the consumed InputStream later and even report who did it 馃槃

Thanks!

Related to (but not covered by): #22985

invalid

All 9 comments

Or maybe its completely related it seems to be a application/x-www-form-urlencoded request as well here, so kind of by design

Yes this is expected, and besides the logging of request details, any other code could cause a similar issue by accessing a request parameter.

Note that you can inject the content reliably as @RequestBody String or @RequestBody ByteArrayResource because we reconstruct the body from request parameters in ServletServerHttpRequest#getBody.

Great, I will do some tests with the @RequestBody

A major drawback is that even the ByteArrayResource contains an interpreted value (in this case url-encoded which make sense but brakes our code), I will have to convince my callers to pass the proper content-type headers :-)

The InputStream should also give you encoded form data. Perhaps you can provide some sample input to explain? Also can you clarify what you mean by the proper content-type header?

So may I interpret this thread as follows?: Receiving stream via HTTP request body is not what Spring is designed to support..? Because by any reason, reading stream can happen before the request body reaches to controller.

This issue concerns the use of one of the getParameter methods on HttpServletRequest which indirectly consume the body of the request body. That's related to form data only, not streaming, and it is how the Servlet API works, with or without Spring.

This does cause the CommonsMultipartResolver to no longer work (if logging on DispatcherServlet is enabled), resulting in an error MissingServletRequestPartException: Required request part 'file' is not present

Should we no longer use CommonsMultipartResolver?

Yes, just use the standard multipart support in the Servlet container.

Was this page helpful?
0 / 5 - 0 ratings