Affects: spring-boot 3.1.4, spring 6.0.12
Issue: When using Spring servlet router functions the Content-Type header is changed by the framework. Spring adds charset=UTF-8
to it, if the client doesn't provide it.
My background: In our project we are calculating a hash-sum over specific request parameters on client and server-side and compare them. Due to the changed Content-Type header the sums don't match.
Steps to reproduce:
You can reproduce this with a simple router function:
@Configuration
class RouterPoC(
private val handlerPoc: HandlerPoc
) {
@Bean
fun demo() = router {
GET("/router", handlerPoc::checkContentType)
}
}
@Component
class HandlerPoc {
private val logger = LoggerFactory.getLogger(this::class.java)
fun checkContentType(request: ServerRequest): ServerResponse {
val contentType = request.headers().contentTypeOrNull()!!.toString()
logger.info(contentType)
check(!contentType.endsWith("charset=UTF-8"))
return ServerResponse.ok().build()
}
}
You can find this demo code here: https://github.com/detached/spring-charset-poc/
And then sending a request with
curl -X GET -H 'Content-Type: application/json' localhost:8080/router
The resulting Content-Type value is application/json;charset=UTF-8
.
I would expect that the header stays untouched like application/json
as it is when using @RestController
instead.
While debugging the code I saw that the CharacterEncodingFilter sets the character encoding of the Request. The charset is added by DefaultServerRequest parsing the servletRequest with ServletServerHttpRequest. The getHeaders() function adds then the charset to the header.
When asking on Stack-Overflow for that I got no good solution.
Comment From: poutsma
As you suspected, this is due to the CharacterEncodingFilter
which Spring Boot includes by default, which adds the UTF-8 encoding if not set. If you don't want this filter to be enabled, put server.servlet.encoding.enabled=false
in your application.properties
.
ServerRequest.headers.contentType
is composed from the contentType
and characterEncoding
properties of the HttpServletRequest
. So it makes sense that the encoding set by CharacterEncodingFilter
is reflected in HandlerPoc
. To do the same what ControllerPoC
does, read the servlet property instead: ServerRequest.servletRequest.contentType
.
Comment From: detached
Thank you very much for the quick answer!