I would like to throw some light on the other part of the question of whether spring supports text/plain?
According to spring docs: what is "consumes" or Consumable Media Types in the @RequestMapping annotation
Definition :
Consumable Media Types
"You can narrow the primary mapping by specifying a list of consumable media types. The request will be matched only if the Content-Type request header matches the specified media type. For example:"
@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
Consumable media type expressions can also be negated as in !text/plain to match to all requests other than those with Content-Type of text/plain.
How spring does the media type matching internally?
Spring Request Driven Design is centred around a servlet called the dispatcher Servlet which uses special beans to process requests one of the bean is RequestMappingHandlerMapping which checks for the media type using
getMatchingCondition method of ConsumesRequestCondition class as shown below.
@Override
public ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) {
if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {
return PRE_FLIGHT_MATCH;
}
if (isEmpty()) {
return this;
}
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(expressions);
result.removeIf(expression -> !expression.match(exchange));
return (!result.isEmpty() ? new ConsumesRequestCondition(result) : null);
}
the get matching condition class uses static inner class ConsumesMediaType Expression which actually makes the check
@Override
protected boolean matchMediaType(ServerWebExchange exchange) throws UnsupportedMediaTypeStatusException {
try {
MediaType contentType = exchange.getRequest().getHeaders().getContentType();
contentType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
return getMediaType().includes(contentType);
}
catch (InvalidMediaTypeException ex) {
throw new UnsupportedMediaTypeStatusException("Can't parse Content-Type [" +
exchange.getRequest().getHeaders().getFirst("Content-Type") +
"]: " + ex.getMessage());
}}
This method returns false once the media type does not match and getMatchingCondition returns null which results in handleNoMatch method of RequestMappingInfoHandlerMapping being called and using PartialMatchHelper class we check for the what type of mismatch it has as shown below and spring throws HttpMediaTypeNotSupportedException error once its see consumes mismatch
if (helper.hasConsumesMismatch()) {
Set<MediaType> mediaTypes = helper.getConsumableMediaTypes();
MediaType contentType = null;
if (StringUtils.hasLength(request.getContentType())) {
try {
contentType = MediaType.parseMediaType(request.getContentType());
}
catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotSupportedException(ex.getMessage());
}
}
throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList<>(mediaTypes));
}
Spring supports all media types as per the IANA https://www.iana.org/assignments/media-types/media-types.xhtml the problem lies only with the curl command as quoted by others.