Remove remaining Spring MVC trailing slash matching

Closes gh-34036
This commit is contained in:
rstoyanchev 2024-12-17 11:11:47 +00:00
parent 2e6046a655
commit 4b9f1732f1
3 changed files with 5 additions and 62 deletions

View File

@ -118,12 +118,12 @@ See the sections on xref:web/webmvc-cors.adoc[CORS] and the xref:web/webmvc-cors
[.small]#xref:web/webflux/reactive-spring.adoc#filters.url-handler[See equivalent in the Reactive stack]# [.small]#xref:web/webflux/reactive-spring.adoc#filters.url-handler[See equivalent in the Reactive stack]#
In previous Spring Framework versions, Spring MVC could be configured to ignore trailing slashes in URL paths In previous Spring Framework versions, Spring MVC could be configured to ignore trailing slashes in URL paths
when mapping incoming requests on controller methods. This could be done by enabling the `setUseTrailingSlashMatch` when mapping incoming requests on controller methods. This means that sending a "GET /home/" request would be
option on the `PathMatchConfigurer`. This means that sending a "GET /home/" request would be handled by a controller handled by a controller method annotated with `@GetMapping("/home")`.
method annotated with `@GetMapping("/home")`.
This option has been retired, but applications are still expected to handle such requests in a safe way. This option was deprecated in 6.0 and removed in 7.0, but applications are still expected to handle such
The `UrlHandlerFilter` Servlet filter has been designed for this purpose. It can be configured to: requests in a safe way. The `UrlHandlerFilter` Servlet filter has been designed for this purpose.
It can be configured to:
* respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant. * respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant.
* wrap the request to act as if the request was sent without a trailing slash and continue the processing of the request. * wrap the request to act as if the request was sent without a trailing slash and continue the processing of the request.

View File

@ -66,8 +66,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
@Nullable @Nullable
private Object rootHandler; private Object rootHandler;
private boolean useTrailingSlashMatch = false;
private boolean lazyInitHandlers = false; private boolean lazyInitHandlers = false;
private final Map<String, Object> handlerMap = new LinkedHashMap<>(); private final Map<String, Object> handlerMap = new LinkedHashMap<>();
@ -101,28 +99,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
return this.rootHandler; return this.rootHandler;
} }
/**
* Whether to match to URLs irrespective of the presence of a trailing slash.
* If enabled a URL pattern such as "/users" also matches to "/users/".
* <p>The default value is {@code false}.
* @deprecated as of 6.0, see
* {@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)}
*/
@Deprecated(since = "6.0")
public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {
this.useTrailingSlashMatch = useTrailingSlashMatch;
if (getPatternParser() != null) {
getPatternParser().setMatchOptionalTrailingSeparator(useTrailingSlashMatch);
}
}
/**
* Whether to match to URLs irrespective of the presence of a trailing slash.
*/
public boolean useTrailingSlashMatch() {
return this.useTrailingSlashMatch;
}
/** /**
* Set whether to lazily initialize handlers. Only applicable to * Set whether to lazily initialize handlers. Only applicable to
* singleton handlers, as prototypes are always lazily initialized. * singleton handlers, as prototypes are always lazily initialized.
@ -360,11 +336,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
if (getPathMatcher().match(registeredPattern, lookupPath)) { if (getPathMatcher().match(registeredPattern, lookupPath)) {
matchingPatterns.add(registeredPattern); matchingPatterns.add(registeredPattern);
} }
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", lookupPath)) {
matchingPatterns.add(registeredPattern + "/");
}
}
} }
String bestMatch = null; String bestMatch = null;
@ -495,11 +466,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
if (getPathMatcher().match(pattern, lookupPath)) { if (getPathMatcher().match(pattern, lookupPath)) {
return new RequestMatchResult(pattern, lookupPath, getPathMatcher()); return new RequestMatchResult(pattern, lookupPath, getPathMatcher());
} }
else if (useTrailingSlashMatch()) {
if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) {
return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher());
}
}
return null; return null;
} }

View File

@ -126,29 +126,6 @@ class PathPatternsRequestConditionTests {
assertThat(match).isEqualTo(expected); assertThat(match).isEqualTo(expected);
} }
@Test
@SuppressWarnings("deprecation")
void matchTrailingSlash() {
MockHttpServletRequest request = createRequest("/foo/");
PathPatternParser patternParser = new PathPatternParser();
patternParser.setMatchOptionalTrailingSeparator(true);
PathPatternsRequestCondition condition = new PathPatternsRequestCondition(patternParser, "/foo");
PathPatternsRequestCondition match = condition.getMatchingCondition(request);
assertThat(match).isNotNull();
assertThat(match.getPatternValues()).containsExactly("/foo");
PathPatternParser strictParser = new PathPatternParser();
strictParser.setMatchOptionalTrailingSeparator(false);
condition = new PathPatternsRequestCondition(strictParser, "/foo");
match = condition.getMatchingCondition(request);
assertThat(match).isNull();
}
@Test @Test
void matchPatternContainsExtension() { void matchPatternContainsExtension() {
MockHttpServletRequest request = createRequest("/foo.html"); MockHttpServletRequest request = createRequest("/foo.html");