Improve no-match handling for @RequestMapping methods
Issue: SPR-9603
This commit is contained in:
@@ -54,10 +54,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given RequestMappingInfo matches the current request and
|
||||
* return a (potentially new) instance with conditions that match the
|
||||
* Check if the given RequestMappingInfo matches the current request and
|
||||
* return a (potentially new) instance with conditions that match the
|
||||
* current request -- for example with a subset of URL patterns.
|
||||
* @returns an info in case of a match; or {@code null} otherwise.
|
||||
* @returns an info in case of a match; or {@code null} otherwise.
|
||||
*/
|
||||
@Override
|
||||
protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) {
|
||||
@@ -88,7 +88,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
Set<String> patterns = info.getPatternsCondition().getPatterns();
|
||||
String bestPattern = patterns.isEmpty() ? lookupPath : patterns.iterator().next();
|
||||
request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestPattern);
|
||||
|
||||
|
||||
Map<String, String> uriTemplateVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath);
|
||||
request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
|
||||
|
||||
@@ -101,40 +101,57 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
/**
|
||||
* Iterate all RequestMappingInfos once again, look if any match by URL at
|
||||
* least and raise exceptions accordingly.
|
||||
*
|
||||
* @throws HttpRequestMethodNotSupportedException
|
||||
*
|
||||
* @throws HttpRequestMethodNotSupportedException
|
||||
* if there are matches by URL but not by HTTP method
|
||||
* @throws HttpMediaTypeNotAcceptableException
|
||||
* @throws HttpMediaTypeNotAcceptableException
|
||||
* if there are matches by URL but not by consumable media types
|
||||
* @throws HttpMediaTypeNotAcceptableException
|
||||
* @throws HttpMediaTypeNotAcceptableException
|
||||
* if there are matches by URL but not by producible media types
|
||||
*/
|
||||
@Override
|
||||
protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> requestMappingInfos,
|
||||
String lookupPath,
|
||||
HttpServletRequest request) throws ServletException {
|
||||
protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> requestMappingInfos,
|
||||
String lookupPath, HttpServletRequest request) throws ServletException {
|
||||
|
||||
Set<String> allowedMethods = new HashSet<String>(6);
|
||||
Set<MediaType> consumableMediaTypes = new HashSet<MediaType>();
|
||||
Set<MediaType> producibleMediaTypes = new HashSet<MediaType>();
|
||||
|
||||
Set<RequestMappingInfo> patternMatches = new HashSet<RequestMappingInfo>();
|
||||
Set<RequestMappingInfo> patternAndMethodMatches = new HashSet<RequestMappingInfo>();
|
||||
|
||||
for (RequestMappingInfo info : requestMappingInfos) {
|
||||
if (info.getPatternsCondition().getMatchingCondition(request) != null) {
|
||||
if (info.getMethodsCondition().getMatchingCondition(request) == null) {
|
||||
patternMatches.add(info);
|
||||
if (info.getMethodsCondition().getMatchingCondition(request) != null) {
|
||||
patternAndMethodMatches.add(info);
|
||||
}
|
||||
else {
|
||||
for (RequestMethod method : info.getMethodsCondition().getMethods()) {
|
||||
allowedMethods.add(method.name());
|
||||
}
|
||||
}
|
||||
if (info.getConsumesCondition().getMatchingCondition(request) == null) {
|
||||
consumableMediaTypes.addAll(info.getConsumesCondition().getConsumableMediaTypes());
|
||||
}
|
||||
if (info.getProducesCondition().getMatchingCondition(request) == null) {
|
||||
producibleMediaTypes.addAll(info.getProducesCondition().getProducibleMediaTypes());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allowedMethods.isEmpty()) {
|
||||
|
||||
if (patternMatches.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else if (patternAndMethodMatches.isEmpty() && !allowedMethods.isEmpty()) {
|
||||
throw new HttpRequestMethodNotSupportedException(request.getMethod(), allowedMethods);
|
||||
}
|
||||
else if (!consumableMediaTypes.isEmpty()) {
|
||||
|
||||
Set<MediaType> consumableMediaTypes;
|
||||
Set<MediaType> producibleMediaTypes;
|
||||
|
||||
if (patternAndMethodMatches.isEmpty()) {
|
||||
consumableMediaTypes = getConsumableMediaTypes(request, patternMatches);
|
||||
producibleMediaTypes = getProdicubleMediaTypes(request, patternMatches);
|
||||
}
|
||||
else {
|
||||
consumableMediaTypes = getConsumableMediaTypes(request, patternAndMethodMatches);
|
||||
producibleMediaTypes = getProdicubleMediaTypes(request, patternAndMethodMatches);
|
||||
}
|
||||
|
||||
if (!consumableMediaTypes.isEmpty()) {
|
||||
MediaType contentType = null;
|
||||
if (StringUtils.hasLength(request.getContentType())) {
|
||||
contentType = MediaType.parseMediaType(request.getContentType());
|
||||
@@ -149,4 +166,24 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe
|
||||
}
|
||||
}
|
||||
|
||||
private Set<MediaType> getConsumableMediaTypes(HttpServletRequest request, Set<RequestMappingInfo> partialMatches) {
|
||||
Set<MediaType> result = new HashSet<MediaType>();
|
||||
for (RequestMappingInfo partialMatch : partialMatches) {
|
||||
if (partialMatch.getConsumesCondition().getMatchingCondition(request) == null) {
|
||||
result.addAll(partialMatch.getConsumesCondition().getConsumableMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<MediaType> getProdicubleMediaTypes(HttpServletRequest request, Set<RequestMappingInfo> partialMatches) {
|
||||
Set<MediaType> result = new HashSet<MediaType>();
|
||||
for (RequestMappingInfo partialMatch : partialMatches) {
|
||||
if (partialMatch.getProducesCondition().getMatchingCondition(request) == null) {
|
||||
result.addAll(partialMatch.getProducesCondition().getProducibleMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user