From fda08852ba9f5d52c149209382c0d03380de413c Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sat, 2 Dec 2017 00:27:15 -0500 Subject: [PATCH] Take content-type from ResponseEntity unconditionally From #9a894a we began using the content-type from the ResponseEntity but cross-checking it still against the requested content type. Arguably there isn't any purpose in cross-checking. The only possible outcomes are: a) it's compatible or b) it's not, which would result in 406 (NOT_ACCEPTABLE). As we've been given explicitly the media type to use, it makes little sense to send 406, ignoring the wish to use that content type. Issue: SPR-16251 --- .../result/HandlerResultHandlerSupport.java | 9 ++-- ...stractMessageConverterMethodProcessor.java | 47 ++++++++++--------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/HandlerResultHandlerSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/HandlerResultHandlerSupport.java index 8b12145f5fb..5f36840ffbe 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/HandlerResultHandlerSupport.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/HandlerResultHandlerSupport.java @@ -116,6 +116,11 @@ public abstract class HandlerResultHandlerSupport implements Ordered { protected MediaType selectMediaType(ServerWebExchange exchange, Supplier> producibleTypesSupplier) { + MediaType contentType = exchange.getResponse().getHeaders().getContentType(); + if (contentType != null && contentType.isConcrete()) { + return contentType; + } + List acceptableTypes = getAcceptableTypes(exchange); List producibleTypes = getProducibleTypes(exchange, producibleTypesSupplier); @@ -152,10 +157,6 @@ public abstract class HandlerResultHandlerSupport implements Ordered { private List getProducibleTypes(ServerWebExchange exchange, Supplier> producibleTypesSupplier) { - MediaType contentType = exchange.getResponse().getHeaders().getContentType(); - if (contentType != null && contentType.isConcrete()) { - return Collections.singletonList(contentType); - } Set mediaTypes = exchange.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE); return (mediaTypes != null ? new ArrayList<>(mediaTypes) : producibleTypesSupplier.get()); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java index 9cc950017f9..36adce100e6 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Set; @@ -210,37 +209,41 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe } } - HttpServletRequest request = inputMessage.getServletRequest(); - List requestedMediaTypes = getAcceptableMediaTypes(request); - MediaType contentType = outputMessage.getHeaders().getContentType(); - List producibleMediaTypes = (contentType != null && contentType.isConcrete() ? - Collections.singletonList(contentType) : getProducibleMediaTypes(request, valueType, declaredType)); + List mediaTypesToUse; - if (outputValue != null && producibleMediaTypes.isEmpty()) { - throw new HttpMessageNotWritableException("No converter found for return value of type: " + valueType); + MediaType contentType = outputMessage.getHeaders().getContentType(); + if (contentType != null && contentType.isConcrete()) { + mediaTypesToUse = Collections.singletonList(contentType); } + else { + HttpServletRequest request = inputMessage.getServletRequest(); + List requestedMediaTypes = getAcceptableMediaTypes(request); + List producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType); - Set compatibleMediaTypes = new LinkedHashSet<>(); - for (MediaType requestedType : requestedMediaTypes) { - for (MediaType producibleType : producibleMediaTypes) { - if (requestedType.isCompatibleWith(producibleType)) { - compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType)); + if (outputValue != null && producibleMediaTypes.isEmpty()) { + throw new HttpMessageNotWritableException( + "No converter found for return value of type: " + valueType); + } + mediaTypesToUse = new ArrayList<>(); + for (MediaType requestedType : requestedMediaTypes) { + for (MediaType producibleType : producibleMediaTypes) { + if (requestedType.isCompatibleWith(producibleType)) { + mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType)); + } } } - } - if (compatibleMediaTypes.isEmpty()) { - if (outputValue != null) { - throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes); + if (mediaTypesToUse.isEmpty()) { + if (outputValue != null) { + throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes); + } + return; } - return; + MediaType.sortBySpecificityAndQuality(mediaTypesToUse); } - List mediaTypes = new ArrayList<>(compatibleMediaTypes); - MediaType.sortBySpecificityAndQuality(mediaTypes); - MediaType selectedMediaType = null; - for (MediaType mediaType : mediaTypes) { + for (MediaType mediaType : mediaTypesToUse) { if (mediaType.isConcrete()) { selectedMediaType = mediaType; break;