Affects: 5.2.0 I'm try to handle a multipart request with follow code:
// A RestController
@RequestMapping(path = "form", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public void testFrom(RequestEntity<MultiValueMap<String, Object>> requestEntity) {
log.info(requestEntity.toString());
}
then tomcat return a 415 code with console output:
2020-11-25 14:42:16,244 WARN (AbstractHandlerExceptionResolver.java:199) - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]
if i use code like this, everything works well:
@RequestMapping(path = "form", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public void testFrom(@RequestBody MultiValueMap<String, Object> requestEntity) {
log.info(requestEntity.toString());
}
After some debug of spring's code, I found in
org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor#resolveArgument
, calling
getHttpEntityType
returns a ParameterizedType.
But when calling org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters(org.springframework.http.HttpInputMessage, org.springframework.core.MethodParameter, java.lang.reflect.Type)
to convert request body, following code make the targetClass
become RequestEntity
instead of MultiValueMap
, cause the fail of message convertion.
Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
if (targetClass == null) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
targetClass = (Class<T>) resolvableType.resolve();
}
Is it a bug?
Comment From: poutsma
The cause of this behavior is the use of RestController
, which means that all parameters use
@ResponseBody
semantics. The method signature would effectively be:
public void testFrom(@RequestBody RequestEntity<MultiValueMap<String, Object>> requestEntity)
Because the form converter can only convert to multi-value maps—and not request entities—the parameter resolution fails.
To use HttpEntity
types in controller method signatures—either as parameters or returns types, do not annotate the class with @RestController
, but with @Controller
instead.