Skip to content

Commit c225b44

Browse files
committed
SPR-5636 - @RequestMapping matching should be insensitive to trailing slashes
1 parent acc8492 commit c225b44

File tree

3 files changed

+23
-4
lines changed

3 files changed

+23
-4
lines changed

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,15 @@ private boolean isPathMatchInternal(String pattern, String lookupPath) {
503503
if (pattern.equals(lookupPath) || pathMatcher.match(pattern, lookupPath)) {
504504
return true;
505505
}
506-
return !(pattern.indexOf('.') != -1) && pathMatcher.match(pattern + ".*", lookupPath);
506+
boolean hasSuffix = pattern.indexOf('.') != -1;
507+
if (!hasSuffix && pathMatcher.match(pattern + ".*", lookupPath)) {
508+
return true;
509+
}
510+
boolean endsWithSlash = pattern.endsWith("/");
511+
if (!endsWithSlash && pathMatcher.match(pattern + "/", lookupPath)) {
512+
return true;
513+
}
514+
return false;
507515
}
508516

509517
private boolean checkParameters(RequestMappingInfo mapping, HttpServletRequest request) {

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
8686

8787
/**
8888
* Set whether to register paths using the default suffix pattern as well:
89-
* i.e. whether "/users" should be registered as "/users.*" too.
89+
* i.e. whether "/users" should be registered as "/users.*" and "/users/" too.
9090
* <p>Default is "true". Turn this convention off if you intend to interpret
9191
* your <code>@RequestMapping</code> paths strictly.
92-
* <p>Note that paths which include a ".xxx" suffix already will not be
92+
* <p>Note that paths which include a ".xxx" suffix or end with "/" already will not be
9393
* transformed using the default suffix pattern in any case.
9494
*/
9595
public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern) {
@@ -168,8 +168,9 @@ public void doWith(Method method) {
168168
*/
169169
protected void addUrlsForPath(Set<String> urls, String path) {
170170
urls.add(path);
171-
if (this.useDefaultSuffixPattern && path.indexOf('.') == -1) {
171+
if (this.useDefaultSuffixPattern && path.indexOf('.') == -1 && !path.endsWith("/")) {
172172
urls.add(path + ".*");
173+
urls.add(path + "/");
173174
}
174175
}
175176

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/UriTemplateServletAnnotationControllerTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ public void crud() throws Exception {
152152
servlet.service(request, response);
153153
assertEquals("list", response.getContentAsString());
154154

155+
request = new MockHttpServletRequest("GET", "/hotels/");
156+
response = new MockHttpServletResponse();
157+
servlet.service(request, response);
158+
assertEquals("list", response.getContentAsString());
159+
155160
request = new MockHttpServletRequest("POST", "/hotels");
156161
response = new MockHttpServletResponse();
157162
servlet.service(request, response);
@@ -162,6 +167,11 @@ public void crud() throws Exception {
162167
servlet.service(request, response);
163168
assertEquals("show-42", response.getContentAsString());
164169

170+
request = new MockHttpServletRequest("GET", "/hotels/42/");
171+
response = new MockHttpServletResponse();
172+
servlet.service(request, response);
173+
assertEquals("show-42", response.getContentAsString());
174+
165175
request = new MockHttpServletRequest("PUT", "/hotels/42");
166176
response = new MockHttpServletResponse();
167177
servlet.service(request, response);

0 commit comments

Comments
 (0)