diff --git a/framework-docs/modules/ROOT/partials/web/uri-patterns.adoc b/framework-docs/modules/ROOT/partials/web/uri-patterns.adoc index f0ff6177a8d..494c50a6c0a 100644 --- a/framework-docs/modules/ROOT/partials/web/uri-patterns.adoc +++ b/framework-docs/modules/ROOT/partials/web/uri-patterns.adoc @@ -26,9 +26,6 @@ `+"/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}+` @@ -49,9 +46,6 @@ `+"/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. |=== \ No newline at end of file diff --git a/spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java b/spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java index 3906e72bd59..9fca26dbc47 100644 --- a/spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java +++ b/spring-web/src/main/java/org/springframework/web/util/pattern/InternalPathPatternParser.java @@ -183,7 +183,6 @@ class InternalPathPatternParser { if (this.pathElementStart != -1) { pushPathElement(createPathElement()); } - verifyPatternElements(this.headPE); return new PathPattern(pathPattern, this.parser, this.headPE); } @@ -439,22 +438,4 @@ class InternalPathPatternParser { this.capturedVariableNames.add(variableName); } - private void verifyPatternElements(@Nullable PathElement headPE) { - PathElement currentElement = headPE; - while (currentElement != null) { - if (currentElement instanceof CaptureSegmentsPathElement || - currentElement instanceof WildcardSegmentsPathElement) { - PathElement nextElement = currentElement.next; - while (nextElement instanceof SeparatorPathElement) { - nextElement = nextElement.next; - } - if (nextElement != null && !(nextElement instanceof LiteralPathElement)) { - throw new PatternParseException(nextElement.pos, this.pathPatternData, - PatternMessage.MULTISEGMENT_PATHELEMENT_NOT_FOLLOWED_BY_LITERAL); - } - } - currentElement = currentElement.next; - } - } - } diff --git a/spring-web/src/main/java/org/springframework/web/util/pattern/PatternParseException.java b/spring-web/src/main/java/org/springframework/web/util/pattern/PatternParseException.java index d9dee2780d4..4fd4833a0a9 100644 --- a/spring-web/src/main/java/org/springframework/web/util/pattern/PatternParseException.java +++ b/spring-web/src/main/java/org/springframework/web/util/pattern/PatternParseException.java @@ -101,7 +101,6 @@ public class PatternParseException extends IllegalArgumentException { ILLEGAL_CHARACTER_IN_CAPTURE_DESCRIPTOR("Char ''{0}'' is not allowed in a captured variable name"), CANNOT_HAVE_MANY_MULTISEGMENT_PATHELEMENTS("Multiple '{*...}' or '**' pattern elements are not allowed"), INVALID_LOCATION_FOR_MULTISEGMENT_PATHELEMENT("'{*...}' or '**' pattern elements should be placed at the start or end of the pattern"), - MULTISEGMENT_PATHELEMENT_NOT_FOLLOWED_BY_LITERAL("'{*...}' or '**' pattern elements should be followed by a literal path element"), BADLY_FORMED_CAPTURE_THE_REST("Expected form when capturing the rest of the path is simply '{*...}'"), MISSING_REGEX_CONSTRAINT("Missing regex constraint on capture"), ILLEGAL_DOUBLE_CAPTURE("Not allowed to capture ''{0}'' twice in the same pattern"), diff --git a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java index e70fe5e8328..1a5f8fd27bc 100644 --- a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternParserTests.java @@ -232,7 +232,6 @@ class PathPatternParserTests { checkError("/{abc}{*foobar}", 1, PatternMessage.CAPTURE_ALL_IS_STANDALONE_CONSTRUCT); checkError("/{abc}{*foobar}{foo}", 1, PatternMessage.CAPTURE_ALL_IS_STANDALONE_CONSTRUCT); checkError("/{*foo}/foo/{*bar}", 18, PatternMessage.CANNOT_HAVE_MANY_MULTISEGMENT_PATHELEMENTS); - checkError("/{*foo}/{bar}", 8, PatternMessage.MULTISEGMENT_PATHELEMENT_NOT_FOLLOWED_BY_LITERAL); checkError("{foo:}", 5, PatternMessage.MISSING_REGEX_CONSTRAINT); checkError("{foo}_{foo}", 0, PatternMessage.ILLEGAL_DOUBLE_CAPTURE, "foo"); checkError("/{bar}/{bar}", 7, PatternMessage.ILLEGAL_DOUBLE_CAPTURE, "bar"); diff --git a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java index 9ab7b66db8c..34728d77703 100644 --- a/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java @@ -185,6 +185,16 @@ class PathPatternTests { checkMatches("/resource/**", "/resource/foobar"); } + @Test + void wildcardSegmentsThenNonLiteral() { + checkMatches("/**/*.js", "/script.js"); + checkMatches("/**/*.js", "/js/script.js"); + checkMatches("/**/*.js", "/files/js/script.js"); + checkMatches("/**/{type}/*.js", "/files/js/script.js"); + + checkNoMatch("/**/*.js", "/files/style.css"); + } + @Test void antPathMatcherTests() { // test exact matching