mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Support wildcard path elements at the start of path patterns
Prior to this commit, the `PathPattern` and `PathPatternParser` would
allow multiple-segments matching and capturing with the following:
* "/files/**" (matching 0-N segments until the end)
* "/files/{*path}" (matching 0-N segments until the end and capturing
the value as the "path" variable)
This would be only allowed as the last path element in the pattern and
the parser would reject other combinations.
This commit expands the support and allows multiple segments matching at
the beginning of the path:
* "/**/index.html" (matching 0-N segments from the start)
* "/{*path}/index.html" (matching 0-N segments until the end and capturing
the value as the "path" variable)
This does come with additional restrictions:
1. "/files/**/file.txt" and "/files/{*path}/file.txt" are invalid,
as multiple segment matching is not allowed in the middle of the
pattern.
2. "/{*path}/files/**" is not allowed, as a single "{*path}" or "/**"
element is allowed in a pattern
3. "/{*path}/{folder}/file.txt" "/**/{folder:[a-z]+}/file.txt" are
invalid because only a literal pattern is allowed right after
multiple segments path elements.
Closes gh-35679
This commit is contained in:
@@ -93,6 +93,10 @@ You can map requests by using glob patterns and wildcards:
|
||||
|===
|
||||
|Pattern |Description |Example
|
||||
|
||||
| `spring`
|
||||
| Literal pattern
|
||||
| `+"/spring"+` matches `+"/spring"+`
|
||||
|
||||
| `+?+`
|
||||
| Matches one character
|
||||
| `+"/pages/t?st.html"+` matches `+"/pages/test.html"+` and `+"/pages/t3st.html"+`
|
||||
@@ -104,10 +108,17 @@ You can map requests by using glob patterns and wildcards:
|
||||
`+"/projects/*/versions"+` matches `+"/projects/spring/versions"+` but does not match `+"/projects/spring/boot/versions"+`
|
||||
|
||||
| `+**+`
|
||||
| Matches zero or more path segments until the end of the path
|
||||
| Matches zero or more path segments
|
||||
| `+"/resources/**"+` matches `+"/resources/file.png"+` and `+"/resources/images/file.png"+`
|
||||
|
||||
`+"/resources/**/file.png"+` is invalid as `+**+` is only allowed at the end of the path.
|
||||
`+"/**/resources"+` matches `+"/spring/resources"+` and `+"/spring/framework/resources"+`
|
||||
|
||||
`+"/resources/**/file.png"+` is invalid as `+**+` is not allowed in the middle of the path.
|
||||
|
||||
`+"/**/{name}/resources"+` is invalid as only a literal pattern is allowed right after `+**+`.
|
||||
`+"/**/project/{project}/resources"+` is allowed.
|
||||
|
||||
`+"/**/spring/**"+` is not allowed, as only a single `+**+`/`+{*path}+` instance is allowed per pattern.
|
||||
|
||||
| `+{name}+`
|
||||
| Matches a path segment and captures it as a variable named "name"
|
||||
@@ -119,9 +130,18 @@ You can map requests by using glob patterns and wildcards:
|
||||
| `/projects/{project:[a-z]+}/versions` matches `/projects/spring/versions` but not `/projects/spring1/versions`
|
||||
|
||||
| `+{*path}+`
|
||||
| Matches zero or more path segments until the end of the path and captures it as a variable named "path"
|
||||
| Matches zero or more path segments and captures it as a variable named "path"
|
||||
| `+"/resources/{*file}"+` matches `+"/resources/images/file.png"+` and captures `+file=/images/file.png+`
|
||||
|
||||
`+"{*path}/resources"+` matches `+"/spring/framework/resources"+` and captures `+path=/spring/framework+`
|
||||
|
||||
`+"/resources/{*path}/file.png"+` is invalid as `{*path}` is not allowed in the middle of the path.
|
||||
|
||||
`+"/{*path}/{name}/resources"+` is invalid as only a literal pattern is allowed right after `{*path}`.
|
||||
`+"/{*path}/project/{project}/resources"+` is allowed.
|
||||
|
||||
`+"/{*path}/spring/**"+` is not allowed, as only a single `+**+`/`+{*path}+` instance is allowed per pattern.
|
||||
|
||||
|===
|
||||
|
||||
Captured URI variables can be accessed with `@PathVariable`, as the following example shows:
|
||||
|
||||
+55
-14
@@ -103,22 +103,63 @@ Spring WebFlux. It was enabled for use in Spring MVC from version 5.3 and is ena
|
||||
default from version 6.0. See xref:web/webmvc/mvc-config/path-matching.adoc[MVC config] for
|
||||
customizations of path matching options.
|
||||
|
||||
`PathPattern` supports the same pattern syntax as `AntPathMatcher`. In addition, it also
|
||||
supports the capturing pattern, for example, `+{*spring}+`, for matching 0 or more path segments
|
||||
at the end of a path. `PathPattern` also restricts the use of `+**+` for matching multiple
|
||||
path segments such that it's only allowed at the end of a pattern. This eliminates many
|
||||
cases of ambiguity when choosing the best matching pattern for a given request.
|
||||
For full pattern syntax please refer to
|
||||
{spring-framework-api}/web/util/pattern/PathPattern.html[PathPattern] and
|
||||
{spring-framework-api}/util/AntPathMatcher.html[AntPathMatcher].
|
||||
You can map requests by using glob patterns and wildcards:
|
||||
|
||||
Some example patterns:
|
||||
[cols="2,3,5"]
|
||||
|===
|
||||
|Pattern |Description |Example
|
||||
|
||||
* `+"/resources/ima?e.png"+` - match one character in a path segment
|
||||
* `+"/resources/*.png"+` - match zero or more characters in a path segment
|
||||
* `+"/resources/**"+` - match multiple path segments
|
||||
* `+"/projects/{project}/versions"+` - match a path segment and capture it as a variable
|
||||
* `++"/projects/{project:[a-z]+}/versions"++` - match and capture a variable with a regex
|
||||
| `spring`
|
||||
| Literal pattern
|
||||
| `+"/spring"+` matches `+"/spring"+`
|
||||
|
||||
| `+?+`
|
||||
| Matches one character
|
||||
| `+"/pages/t?st.html"+` matches `+"/pages/test.html"+` and `+"/pages/t3st.html"+`
|
||||
|
||||
| `+*+`
|
||||
| Matches zero or more characters within a path segment
|
||||
| `+"/resources/*.png"+` matches `+"/resources/file.png"+`
|
||||
|
||||
`+"/projects/*/versions"+` matches `+"/projects/spring/versions"+` but does not match `+"/projects/spring/boot/versions"+`
|
||||
|
||||
| `+**+`
|
||||
| Matches zero or more path segments
|
||||
| `+"/resources/**"+` matches `+"/resources/file.png"+` and `+"/resources/images/file.png"+`
|
||||
|
||||
`+"/**/resources"+` matches `+"/spring/resources"+` and `+"/spring/framework/resources"+`
|
||||
|
||||
`+"/resources/**/file.png"+` is invalid as `+**+` is not allowed in the middle of the path.
|
||||
|
||||
`+"/**/{name}/resources"+` is invalid as only a literal pattern is allowed right after `+**+`.
|
||||
`+"/**/project/{project}/resources"+` is allowed.
|
||||
|
||||
`+"/**/spring/**"+` is not allowed, as only a single `+**+`/`+{*path}+` instance is allowed per pattern.
|
||||
|
||||
| `+{name}+`
|
||||
| Matches a path segment and captures it as a variable named "name"
|
||||
| `+"/projects/{project}/versions"+` matches `+"/projects/spring/versions"+` and captures `+project=spring+`
|
||||
|
||||
`+"/projects/{project}/versions"+` does not match `+"/projects/spring/framework/versions"+` as it captures a single path segment.
|
||||
|
||||
| `{name:[a-z]+}`
|
||||
| Matches the regexp `"[a-z]+"` as a path variable named "name"
|
||||
| `"/projects/{project:[a-z]+}/versions"` matches `"/projects/spring/versions"` but not `"/projects/spring1/versions"`
|
||||
|
||||
| `+{*path}+`
|
||||
| Matches zero or more path segments and captures it as a variable named "path"
|
||||
| `+"/resources/{*file}"+` matches `+"/resources/images/file.png"+` and captures `+file=/images/file.png+`
|
||||
|
||||
`+"{*path}/resources"+` matches `+"/spring/framework/resources"+` and captures `+path=/spring/framework+`
|
||||
|
||||
`+"/resources/{*path}/file.png"+` is invalid as `{*path}` is not allowed in the middle of the path.
|
||||
|
||||
`+"/{*path}/{name}/resources"+` is invalid as only a literal pattern is allowed right after `{*path}`.
|
||||
`+"/{*path}/project/{project}/resources"+` is allowed.
|
||||
|
||||
`+"/{*path}/spring/**"+` is not allowed, as only a single `+**+`/`+{*path}+` instance is allowed per pattern.
|
||||
|
||||
|===
|
||||
|
||||
Captured URI variables can be accessed with `@PathVariable`. For example:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user