Affects: 5.2.23
Problem
When org.springframework.http.HttpHeaders.getContentType
is called on an invalid content type value, it throws an InvalidMediaTypeException
.
HttpHeaders.getContentType
states that it "Returns null when the content-type is unknown", and is annotated with @Nullable
which leads the consumer to assume it won't throw an exception, and would return null if an invalid content-type was provided.
https://github.com/spring-projects/spring-framework/blob/a3c89092e1ff9d07e4143af383090afa91a62c15/spring-web/src/main/java/org/springframework/http/HttpHeaders.java#L990-L996
The exception is thrown because HttpHeaders.getContentType
delegates the MediaType
parsing to MediaType.parseMediaType
which either reutrns a non-null MediaType
or throws an InvalidMediaTypeException
.
https://github.com/spring-projects/spring-framework/blob/a3c89092e1ff9d07e4143af383090afa91a62c15/spring-web/src/main/java/org/springframework/http/HttpHeaders.java#L998
Impact on spring-boot-webflux projects
On a @RestController
annotated class with a @PostMapping
method that accepts a @RequestBody
annotated argument, a HTTP POST
request with an invalid Content-Type
header will trigger an internal server error:
{
"timestamp": "2022-11-24T05:07:43.258+00:00",
"path": "/",
"status": 500,
"error": "Internal Server Error",
"requestId": "b68b77c7-1"
}
This is because the AbstractMessageReaderArgumentResolver.readBody
attempts to call HttpHeaders.getContentType
and store it as a variable contentType
, assuming it won't throw an Exception.
https://github.com/spring-projects/spring-framework/blob/a3c89092e1ff9d07e4143af383090afa91a62c15/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/AbstractMessageReaderArgumentResolver.java#L135-L148
Steps to reproduce
- Create a Spring Boot project with
spring-boot-starter-webflux
dependency -
Add a
RestController
annotated class with the following method: ```@PostMapping("/") public String index(@RequestBody String body) { return body; }
`` 3. Run the application, and make a HTTP
POSTrequest to the route with an invalid
Content-Typeheader.
curl -X POST http://localhost:8080/ -H "Content-Type: unknown` 4. An internal server error is triggered
Proposal
Wrap the call to MediaType.parseMediaType
in a try catch
block which returns null
if an InvalidMediaTypeException
is caught.
Comment From: rstoyanchev
I think "content-type is unknown" means the client didn't specify it and therefore it is not known to the server, in which case the method does return null
as the annotation correctly indicates. The Javadoc, however, should also have @throws InvalidMediaTypeException
since it can fail with a parse error. I'll update the Javadoc there.
As for AbstractMessageReaderArgumentResolver
, by comparison Spring MVC's AbstractMessageConverterMethodArgumentResolver does expect and handle this as an exception that results in a 400 response. We need to the same.
Thanks for spotting and reporting these.