Description
Hello.
I found illogical behavior of the getBody method of the org.springframework.http.server.ServletServerHttpRequest.
If you send POST requests to the server with a form-url-encoded body, the behavior changes depending on the presence of query parameters in the request url.
If query parameters are not passed, the request body is recoded (decoded/encoded) into utf-8 encoding based on the previously parsed form-url-encoded parameters.
If at least one query parameter is passed, the request body is not recoded.
The behavior is unnoticeable if the original request encoding is utf-8, but is very noticeable if a different encoding is used.
See the example application in the attachment.
bug-spring-web.zip
Test 1.
Send a request with query parameter q and the string "ааа" url-encoded in windows-1251 as %e0%e0%e0 in the body.
> curl --trace - -H 'Content-Type: application/x-www-form-urlencoded;charset=windows-1251' --data-binary 'x=%e0%e0%e0' http://127.0.0.1:8080/path?q=1
In the server logs we will see something like:
: url: http://127.0.0.1:8080/path?q=1
: params: {q=1}
: content-type: [application/x-www-form-urlencoded;charset=windows-1251]
: content-length: [11]
: body: x=%e0%e0%e0
All is correct.
Test 2.
Send a request with the same body but without query parameter.
> curl --trace - -H 'Content-Type: application/x-www-form-urlencoded;charset=windows-1251' --data-binary 'x=%e0%e0%e0' http://127.0.0.1:8080/path
In the server logs we will see something like:
: url: http://127.0.0.1:8080/path
: params: {x=ааа}
: content-type: [application/x-www-form-urlencoded;charset=windows-1251]
: content-length: [11]
: body: x=%D0%B0%D0%B0%D0%B0
Now we see that the request body has been recoded.
The actual content encoding is utf-8 and the actual content length is 20 bytes.
But in the request headers we see old values, which is incorrect.
As a result recoding does not always occur.
And when recoding occurs, the content headers do not reflect reality.