-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
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.
spring-framework/spring-web/src/main/java/org/springframework/http/HttpHeaders.java
Lines 990 to 996 in a3c8909
/** | |
* Return the {@linkplain MediaType media type} of the body, as specified | |
* by the {@code Content-Type} header. | |
* <p>Returns {@code null} when the content-type is unknown. | |
*/ | |
@Nullable | |
public MediaType getContentType() { |
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
.
spring-framework/spring-web/src/main/java/org/springframework/http/HttpHeaders.java
Line 998 in a3c8909
return (StringUtils.hasLength(value) ? MediaType.parseMediaType(value) : null); |
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.
Lines 135 to 148 in a3c8909
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam, | |
boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) { | |
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam); | |
ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType); | |
Class<?> resolvedType = bodyType.resolve(); | |
ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null); | |
ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType); | |
isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty()); | |
ServerHttpRequest request = exchange.getRequest(); | |
ServerHttpResponse response = exchange.getResponse(); | |
MediaType contentType = request.getHeaders().getContentType(); |
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; }
- Run the application, and make a HTTP
POST
request to the route with an invalidContent-Type
header.
curl -X POST http://localhost:8080/ -H "Content-Type: unknown
- 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.
Activity
rstoyanchev commentedon Nov 25, 2022
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.
[-]HttpHeaders.getContentType throws InvalidMediaTypeException when the content type is unknown[/-][+]500 error from WebFlux when parsing Content-Type leads to InvalidMediaTypeException[/+]Improve invalid Content-Type handling in WebFlux