SPR-6467 - Allow ContentNegotiatingViewResolver to be strict ant return a 406 if no view found
This commit is contained in:
@@ -31,6 +31,7 @@ import javax.activation.FileTypeMap;
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.core.OrderComparator;
|
||||
@@ -114,6 +115,8 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
private boolean favorParameter = false;
|
||||
|
||||
private String parameterName = "format";
|
||||
|
||||
private boolean useNotAcceptableStatusCode = false;
|
||||
|
||||
private boolean ignoreAcceptHeader = false;
|
||||
|
||||
@@ -125,7 +128,6 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
|
||||
private List<ViewResolver> viewResolvers;
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
@@ -174,6 +176,20 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
this.ignoreAcceptHeader = ignoreAcceptHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a {@link HttpServletResponse#SC_NOT_ACCEPTABLE 406 Not Acceptable} status code should be
|
||||
* returned if no suitable view can be found.
|
||||
*
|
||||
* <p>Default is {@code false}, meaning that this view resolver returns {@code null} for
|
||||
* {@link #resolveViewName(String, Locale)} when an acceptable view cannot be found. This will allow for view
|
||||
* resolvers chaining. When this property is set to {@code true},
|
||||
* {@link #resolveViewName(String, Locale)} will respond with a view that sets the response status to
|
||||
* {@code 406 Not Acceptable} instead.
|
||||
*/
|
||||
public void setUseNotAcceptableStatusCode(boolean useNotAcceptableStatusCode) {
|
||||
this.useNotAcceptableStatusCode = useNotAcceptableStatusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mapping from file extensions to media types.
|
||||
* <p>When this mapping is not set or when an extension is not present, this view resolver
|
||||
@@ -337,7 +353,6 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
Collections.sort(requestedMediaTypes);
|
||||
}
|
||||
|
||||
SortedMap<MediaType, View> views = new TreeMap<MediaType, View>();
|
||||
List<View> candidateViews = new ArrayList<View>();
|
||||
for (ViewResolver viewResolver : this.viewResolvers) {
|
||||
View view = viewResolver.resolveViewName(viewName, locale);
|
||||
@@ -349,6 +364,7 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
candidateViews.addAll(this.defaultViews);
|
||||
}
|
||||
|
||||
SortedMap<MediaType, View> views = new TreeMap<MediaType, View>();
|
||||
for (View candidateView : candidateViews) {
|
||||
String contentType = candidateView.getContentType();
|
||||
if (StringUtils.hasText(contentType)) {
|
||||
@@ -373,11 +389,10 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
return view;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
return useNotAcceptableStatusCode ? new NotAcceptableView() : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard-coded JAF dependency.
|
||||
*/
|
||||
@@ -421,4 +436,15 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
|
||||
}
|
||||
}
|
||||
|
||||
private static class NotAcceptableView implements View {
|
||||
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user