-
Notifications
You must be signed in to change notification settings - Fork 268
Description
When trying to log a multipart request with a HttpLogFormatter
the request body is logged correctly, but when the request eventually reaches Spring's MultipartResolver
, it cannot be resolved anymore and a MissingServletRequestPartException
is thrown. The behavior in Spring seems similar to #637, but it is reproducible on the latest Logbook version 2.14.0.
Description
I encountered this behavior when I tried to log the body of a multipart request with Logbook. By default, there is a BodyReplacer
in place which just replaces the body with <multipart>
, so I disabled the existing RequestFilter
. Requests would then be logged inside of a custom Sink
which uses the JsonHttpLogFormatter to format the request, but it is also reproducible with the DefaultHttpLogFormatter
.
Code has been ported from Kotlin to Java for the sake of this report - I hope it's compilable, but at the very least it should be understandable.
class CustomSink extends Sink {
private HttpLogFormatter jsonHttpLogFormatter = JsonHttpLogFormatter(); // DefaultHttpLogFormatter has the same issue
@Override
void write(Precorrelation precorrelation, HttpRequest request) {
RawJsonAppendingMarker marker = new RawJsonAppendingMarker("http", jsonHttpLogFormatter.format(precorrelation, request));
String message = request.getMethod() + request.getRequestUri();
log.info(marker, message);
}
...
}
When I instead just put a static String inside the RawJsonAppendingMarker
, the request comes out intact, so the issue seems to be related to calling the HttpLogFormatter.
Expected Behavior
When formatting a request with a HttpLogFormatter
, the request should afterwards still work as expected when it reaches the controller.
Actual Behavior
When formatting a request with a HttpLogFormatter
, Spring will not be able to resolve the request afterwards and throw an exception.
Possible Fix
Not sure if that really counts a fix, it's more of a nice-to-have. What I ended up doing to solve the problem is writing my own HandlerInterceptor
which logs the request (which is a javax.servlet.http.HttpServletRequest
here) as the individual parts. If the request would be resolved by Logbook, maybe instead of being restricted to just logging the body
, the user could be able to log individual parts through Filters (e.g. log text, but don't log files).
Steps to Reproduce
either
- checkout the repo and run the requests mentioned in the readme
or
- create a simple
RestController
in Spring which takes a multipart request through POST e.g.public void create(@RequestPart("text") String text) { }
- disable the default
RequestFilter
by settingRequestFilter.none()
to avoid replacement of the body. - create a custom sink for logging similar to the one mentioned above.
- call
HttpLogFormatter.format
on the request and precorrelation - send a simple multipart request, e.g.
POST http://localhost:8080/test
Accept: application/vnd.api+json
Content-Type: multipart/form-data; boundary=abc
--abc
Content-Disposition: form-data; name="text"
Content-Type: text/plain
Hello World
--abc--
Context
I was unable to log the body of the multipart request in order to understand whether or not it was correctly formatted and had the correct headers and parts.
Your Environment
- Version used: 2.14.0
- Link to your project: HttpLogFormatterDemo