Skip to content

500 error from WebFlux when parsing Content-Type leads to InvalidMediaTypeException #29565

Closed
@prcjac

Description

@prcjac

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.

/**
* 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.

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.

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

  1. Create a Spring Boot project with spring-boot-starter-webflux dependency
  2. 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 POST request to the route with an invalid Content-Type header.
    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.

Activity

rstoyanchev

rstoyanchev commented on Nov 25, 2022

@rstoyanchev
Contributor

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.

self-assigned this
on Nov 25, 2022
added
in: webIssues in web modules (web, webmvc, webflux, websocket)
and removed on Nov 25, 2022
added this to the 5.3.25 milestone on Nov 25, 2022
changed the title [-]HttpHeaders.getContentType throws InvalidMediaTypeException when the content type is unknown[/-] [+]500 error from WebFlux when parsing Content-Type leads to InvalidMediaTypeException[/+] on Nov 25, 2022
modified the milestones: 5.3.25, 6.0.3 on Dec 5, 2022

2 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @rstoyanchev@prcjac@spring-projects-issues

      Issue actions

        500 error from WebFlux when parsing Content-Type leads to InvalidMediaTypeException · Issue #29565 · spring-projects/spring-framework