-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Closed
Labels
in: webIssues in web modules (web, webmvc, webflux, websocket)Issues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancementA general enhancement
Milestone
Description
Antonio Marrero opened SPR-10550 and commented
Problem:
Normally the pattern "/" is used to handle the requests that don't match any of the other Servlet requests, therefore its priority should be the lowest.
When there is a URI pattern with 3 or more PathVariable (i.e "/matches/{matchId}/periods/{periodId}/teams/{teamId}/results") the default URI ("/") takes precedence.
Cause:
The problem is that the method AntPathMatcher.compare is giving higher priority to the patterns with less brackets "{}" and wildcards "*". See below an extract of code from the compare method:
int wildCardCount1 = getWildCardCount(pattern1);
int wildCardCount2 = getWildCardCount(pattern2);
int bracketCount1 = StringUtils.countOccurrencesOf(pattern1, "{");
int bracketCount2 = StringUtils.countOccurrencesOf(pattern2, "{");
int totalCount1 = wildCardCount1 + bracketCount1;
int totalCount2 = wildCardCount2 + bracketCount2;
if (totalCount1 != totalCount2) {
return totalCount1 - totalCount2;
}
Solution:
The pattern "/**" should have a special treatment like null has. See below a proposed solution:
public int compare(String pattern1, String pattern2) {
if (pattern1 == null && pattern2 == null) {
return 0;
}
else if (pattern1 == null) {
return 1;
}
else if (pattern2 == null) {
return -1;
}
boolean pattern1EqualsPath = pattern1.equals(path);
boolean pattern2EqualsPath = pattern2.equals(path);
if (pattern1EqualsPath && pattern2EqualsPath) {
return 0;
}
else if (pattern1EqualsPath) {
return -1;
}
else if (pattern2EqualsPath) {
return 1;
}
// Setting lower priority to "/**"
if(pattern1.equals("/**")){
return 1;
}else if (pattern2.equals("/**")){
return -1;
}
int wildCardCount1 = getWildCardCount(pattern1);
int wildCardCount2 = getWildCardCount(pattern2);
int bracketCount1 = StringUtils.countOccurrencesOf(pattern1, "{");
int bracketCount2 = StringUtils.countOccurrencesOf(pattern2, "{");
int totalCount1 = wildCardCount1 + bracketCount1;
int totalCount2 = wildCardCount2 + bracketCount2;
if (totalCount1 != totalCount2) {
return totalCount1 - totalCount2;
}
int pattern1Length = getPatternLength(pattern1);
int pattern2Length = getPatternLength(pattern2);
if (pattern1Length != pattern2Length) {
return pattern2Length - pattern1Length;
}
if (wildCardCount1 < wildCardCount2) {
return -1;
}
else if (wildCardCount2 < wildCardCount1) {
return 1;
}
if (bracketCount1 < bracketCount2) {
return -1;
}
else if (bracketCount2 < bracketCount1) {
return 1;
}
return 0;
}
Affects: 3.2.2
Issue Links:
- AntPathMatcher.AntPatternComparator algorithm wrong for hierarchical matches [SPR-8683] #13325 AntPathMatcher.AntPatternComparator algorithm wrong for hierarchical matches ("is duplicated by")
- AntPatternComparator prefers a less specific match when brackets occur [SPR-8355] #13002 AntPatternComparator prefers a less specific match when brackets occur ("is duplicated by")
- Doc: Spring MVC and the most 'specific' @RequestMapping URL pattern [SPR-10576] #15205 Doc: Spring MVC and the most 'specific'
@RequestMappingURL pattern
Metadata
Metadata
Assignees
Labels
in: webIssues in web modules (web, webmvc, webflux, websocket)Issues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancementA general enhancement