diff --git a/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc b/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc
index c56ed3beeb9..6c90c45a0e0 100644
--- a/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc
+++ b/framework-docs/modules/ROOT/pages/web/webflux/reactive-spring.adoc
@@ -418,16 +418,24 @@ See the section on xref:web/webflux-cors.adoc[CORS] and the xref:web/webflux-cor
You may want your controller endpoints to match routes with or without a trailing slash in the URL path.
For example, both "GET /home" and "GET /home/" should be handled by a controller method annotated with `@GetMapping("/home")`.
-Adding trailing slash variants to all mapping declarations is not the best way to handle this use case.
-The `UrlHandlerFilter` web filter has been designed for this purpose. It can be configured to:
+Spring provides `UrlHandlerFilter` that removes the trailing slash from URL paths to ensure a consistent view of paths with or without a trailing slash.
+This is important to avoid a mismatch between URL-based authorization decisions and web framework request mappings.
+The filter can remove the trailing slash in one of a couple of ways:
-* respond with an HTTP redirect status when receiving URLs with trailing slashes, sending browsers to the non-trailing slash URL variant.
-* mutate the request to act as if the request was sent without a trailing slash and continue the processing of the request.
+* respond with an HTTP redirect status that sends clients to the same path without a trailing slash.
+* mutate the request to remove the trailing slash.
Here is how you can instantiate and configure a `UrlHandlerFilter` for a blog application:
include-code::./UrlHandlerFilterConfiguration[tag=config,indent=0]
+Keep in mind the following:
+
+- the root path `"/"` is excluded from trailing slash handling.
+- prefer `@RequestMapping` over
+- `@RequestMapping("/")` adds a trailing slash to a type-level mapping, and therefore will
+not map when trailing slash handling applies; use `@RequestMapping` (no path attribute) instead.
+
[[webflux-exception-handler]]
== Exceptions
diff --git a/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc b/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc
index 53ce8bfc4e9..6a445ab3616 100644
--- a/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc
+++ b/framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc
@@ -120,17 +120,27 @@ See the sections on xref:web/webmvc-cors.adoc[CORS] and the xref:web/webmvc-cors
== URL Handler
[.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")`.
+You may want your controller endpoints to match routes with or without a trailing slash in the URL path.
+For example, both "GET /home" and "GET /home/" should 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:
+Spring provides `UrlHandlerFilter` that removes the trailing slash from URL paths to ensure a consistent view of paths with or without a trailing slash.
+This is important to avoid a mismatch between URL-based authorization decisions and web framework request mappings.
+The filter can remove the trailing slash in one of a couple of ways:
-* 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.
+* respond with an HTTP redirect status that sends clients to the same path without a trailing slash.
+* wrap the request to remove the trailing slash.
+
+NOTE: Historically Spring MVC supported trailing slash matching of URL paths.
+This capability was deprecated in 6.0 for security reasons and removed in 7.0 with
+`UrlHandlerFilter` providing a safer alternative.
Here is how you can instantiate and configure a `UrlHandlerFilter` for a blog application:
include-code::./UrlHandlerFilterConfiguration[tag=config,indent=0]
+
+Keep in mind the following:
+
+- the root path `"/"` is excluded from trailing slash handling.
+- prefer `@RequestMapping` over
+- `@RequestMapping("/")` adds a trailing slash to a type-level mapping, and therefore will
+not map when trailing slash handling applies; use `@RequestMapping` (no path attribute) instead.
diff --git a/spring-web/src/main/java/org/springframework/web/filter/UrlHandlerFilter.java b/spring-web/src/main/java/org/springframework/web/filter/UrlHandlerFilter.java
index cc7d206d6df..7711d197e23 100644
--- a/spring-web/src/main/java/org/springframework/web/filter/UrlHandlerFilter.java
+++ b/spring-web/src/main/java/org/springframework/web/filter/UrlHandlerFilter.java
@@ -100,10 +100,18 @@ public final class UrlHandlerFilter extends OncePerRequestFilter {
/**
- * Create a builder by adding a handler for URL's with a trailing slash.
- * @param pathPatterns path patterns to map the handler to, for example,
- * "/path/*", "/path/**",
- * "/path/foo/".
+ * Add a handler that removes the trailing slash from URL paths to ensure
+ * consistent interpretation of paths with or without a trailing slash for
+ * requestion mapping purposes. This is important especially to avoid
+ * misalignment between URL-based authorization decisions and web framework
+ * request mappings.
+ *
The root path {@code "/"} is excluded from trailing slash handling. + *
Note: A method-level {@code @RequestMapping("/")} adds
+ * a trailing slash to a type-level prefix mapping, and therefore would never
+ * match to a URL with the trailing slash removed. Use {@code @RequestMapping}
+ * without a path instead to avoid the trailing slash in the mapping.
+ * @param pathPatterns patterns to map the handler to, e.g.
+ * "/path/*", "/path/**", "/path/foo/"
* @return a spec to configure the trailing slash handler with
* @see Builder#trailingSlashHandler(String...)
*/
diff --git a/spring-web/src/main/java/org/springframework/web/filter/reactive/UrlHandlerFilter.java b/spring-web/src/main/java/org/springframework/web/filter/reactive/UrlHandlerFilter.java
index d7d02ad40cb..91bc066f8ff 100644
--- a/spring-web/src/main/java/org/springframework/web/filter/reactive/UrlHandlerFilter.java
+++ b/spring-web/src/main/java/org/springframework/web/filter/reactive/UrlHandlerFilter.java
@@ -91,10 +91,18 @@ public final class UrlHandlerFilter implements WebFilter {
}
/**
- * Create a builder by adding a handler for URL's with a trailing slash.
- * @param pathPatterns path patterns to map the handler to, e.g.
- * "/path/*", "/path/**",
- * "/path/foo/".
+ * Add a handler that removes the trailing slash from URL paths to ensure
+ * consistent interpretation of paths with or without a trailing slash for
+ * requestion mapping purposes. This is important especially to avoid
+ * misalignment between URL-based authorization decisions and web framework
+ * request mappings.
+ *
The root path {@code "/"} is excluded from trailing slash handling. + *
Note: A method-level {@code @RequestMapping("/")} adds
+ * a trailing slash to a type-level prefix mapping, and therefore would never
+ * match to a URL with the trailing slash removed. Use {@code @RequestMapping}
+ * without a path instead to avoid the trailing slash in the mapping.
+ * @param pathPatterns patterns to map the handler to, e.g.
+ * "/path/*", "/path/**", "/path/foo/"
* @return a spec to configure the trailing slash handler with
* @see Builder#trailingSlashHandler(String...)
*/