Fix content negotiation issue with sort by q-value
Before this fix the q-value of media types in the Accept header were ignored when using the new RequestMappingHandlerAdapter in combination with @ResponseBody and HttpMessageConverters. Issue: SPR-9160
This commit is contained in:
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -117,7 +116,7 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||
}
|
||||
|
||||
List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);
|
||||
MediaType.sortBySpecificity(mediaTypes);
|
||||
MediaType.sortBySpecificityAndQuality(mediaTypes);
|
||||
|
||||
MediaType selectedMediaType = null;
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
@@ -131,6 +130,8 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||
}
|
||||
}
|
||||
|
||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||
|
||||
if (selectedMediaType != null) {
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
|
||||
@@ -188,14 +189,12 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the more specific media type using the q-value of the first media type for both.
|
||||
* Return the more specific of the acceptable and the producible media types
|
||||
* with the q-value of the former.
|
||||
*/
|
||||
private MediaType getMostSpecificMediaType(MediaType type1, MediaType type2) {
|
||||
double quality = type1.getQualityValue();
|
||||
Map<String, String> params = Collections.singletonMap("q", String.valueOf(quality));
|
||||
MediaType t1 = new MediaType(type1, params);
|
||||
MediaType t2 = new MediaType(type2, params);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(t1, t2) <= 0 ? type1 : type2;
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
produceType = produceType.copyQualityValue(acceptType);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) < 0 ? acceptType : produceType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -101,6 +101,7 @@ import org.springframework.web.util.WebUtils;
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.0
|
||||
* @see ViewResolver
|
||||
* @see InternalResourceViewResolver
|
||||
@@ -354,13 +355,13 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
}
|
||||
}
|
||||
}
|
||||
List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);
|
||||
MediaType.sortByQualityValue(mediaTypes);
|
||||
List<MediaType> selectedMediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);
|
||||
MediaType.sortBySpecificityAndQuality(selectedMediaTypes);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Requested media types are " + mediaTypes + " based on Accept header types " +
|
||||
logger.debug("Requested media types are " + selectedMediaTypes + " based on Accept header types " +
|
||||
"and producible media types " + producibleMediaTypes + ")");
|
||||
}
|
||||
return mediaTypes;
|
||||
return selectedMediaTypes;
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -395,14 +396,12 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the more specific media type using the q-value of the first media type for both.
|
||||
* Return the more specific of the acceptable and the producible media types
|
||||
* with the q-value of the former.
|
||||
*/
|
||||
private MediaType getMostSpecificMediaType(MediaType type1, MediaType type2) {
|
||||
double quality = type1.getQualityValue();
|
||||
Map<String, String> params = Collections.singletonMap("q", String.valueOf(quality));
|
||||
MediaType t1 = new MediaType(type1, params);
|
||||
MediaType t2 = new MediaType(type2, params);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(t1, t2) <= 0 ? type1 : type2;
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
produceType = produceType.copyQualityValue(acceptType);
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceType) < 0 ? acceptType : produceType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user