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]#
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`
option on the `PathMatchConfigurer`. This means that sending a "GET /home/" request would be handled by a controller
method annotated with `@GetMapping("/home")`.
when mapping incoming requests on controller methods. This means that sending a "GET /home/" request would be
handled by a controller method annotated with `@GetMapping("/home")`.
This option has been retired, but applications are still expected to handle such requests in a safe way.
The `UrlHandlerFilter` Servlet filter has been designed for this purpose. It can be configured to:
This option was deprecated in 6.0 and removed in 7.0, but applications are still expected to handle such
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.
* 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
private Object rootHandler;
private boolean useTrailingSlashMatch = false;
private boolean lazyInitHandlers = false;
private final Map<String, Object> handlerMap = new LinkedHashMap<>();
@ -101,28 +99,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
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
* singleton handlers, as prototypes are always lazily initialized.
@ -360,11 +336,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
if (getPathMatcher().match(registeredPattern, lookupPath)) {
matchingPatterns.add(registeredPattern);
}
else if (useTrailingSlashMatch()) {
if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", lookupPath)) {
matchingPatterns.add(registeredPattern + "/");
}
}
}
String bestMatch = null;
@ -495,11 +466,6 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i
if (getPathMatcher().match(pattern, lookupPath)) {
return new RequestMatchResult(pattern, lookupPath, getPathMatcher());
}
else if (useTrailingSlashMatch()) {
if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) {
return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher());
}
}
return null;
}

View File

@ -126,29 +126,6 @@ class PathPatternsRequestConditionTests {
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
void matchPatternContainsExtension() {
MockHttpServletRequest request = createRequest("/foo.html");