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...) */