Skip to content

Commit 62fa20f

Browse files
committed
PathPattern#matchAndExtract minor refactoring
Consistent behavior with matches(PathContainer), the two had slightly different logic for handling of empty paths. Make matchAndExtract independantly usable without the need to call matches(PathContainer) first. Essentially no longer raising ISE if the pattern doesn't match but simply returning null.
1 parent dccedd5 commit 62fa20f

File tree

3 files changed

+21
-29
lines changed

3 files changed

+21
-29
lines changed

spring-web/src/main/java/org/springframework/web/util/pattern/PathPattern.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,28 @@ else if (!hasLength(pathContainer)) {
175175
MatchingContext matchingContext = new MatchingContext(pathContainer, false);
176176
return this.head.matches(0, matchingContext);
177177
}
178-
178+
179179
/**
180180
* Match this pattern to the given URI path and return extracted URI template
181181
* variables as well as path parameters (matrix variables).
182182
* @param pathContainer the candidate path to attempt to match against
183-
* @return info object with the extracted variables
184-
* @throws IllegalStateException if the path does not match the pattern
183+
* @return info object with the extracted variables, or {@code null} for no match
185184
*/
185+
@Nullable
186186
public PathMatchInfo matchAndExtract(PathContainer pathContainer) {
187-
MatchingContext matchingContext = new MatchingContext(pathContainer, true);
188-
if (this.head != null && this.head.matches(0, matchingContext)) {
189-
return matchingContext.getPathMatchResult();
187+
if (this.head == null) {
188+
return hasLength(pathContainer) ? null : PathMatchInfo.EMPTY;
190189
}
191190
else if (!hasLength(pathContainer)) {
192-
return PathMatchInfo.EMPTY;
193-
}
194-
else {
195-
throw new IllegalStateException(
196-
"Pattern \"" + this + "\" is not a match for \"" + pathContainer.value() + "\"");
191+
if (this.head instanceof WildcardTheRestPathElement || this.head instanceof CaptureTheRestPathElement) {
192+
pathContainer = EMPTY_PATH; // Will allow CaptureTheRest to bind the variable to empty
193+
}
194+
else {
195+
return null;
196+
}
197197
}
198+
MatchingContext matchingContext = new MatchingContext(pathContainer, true);
199+
return this.head.matches(0, matchingContext) ? matchingContext.getPathMatchResult() : null;
198200
}
199201

200202
/**

spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -768,20 +768,10 @@ public void extractUriTemplateVariables() throws Exception {
768768
checkCapture("/{page}.*", "/42.html", "page", "42");
769769
checkCapture("/A-{B}-C", "/A-b-C", "B", "b");
770770
checkCapture("/{name}.{extension}", "/test.html", "name", "test", "extension", "html");
771-
try {
772-
checkCapture("/{one}/", "//", "one", "");
773-
fail("Expected exception");
774-
}
775-
catch (IllegalStateException e) {
776-
assertEquals("Pattern \"/{one}/\" is not a match for \"//\"", e.getMessage());
777-
}
778-
try {
779-
checkCapture("", "/abc");
780-
fail("Expected exception");
781-
}
782-
catch (IllegalStateException e) {
783-
assertEquals("Pattern \"\" is not a match for \"/abc\"", e.getMessage());
784-
}
771+
772+
assertNull(checkCapture("/{one}/", "//"));
773+
assertNull(checkCapture("", "/abc"));
774+
785775
assertEquals(0, checkCapture("", "").getUriVariables().size());
786776
checkCapture("{id}", "99", "id", "99");
787777
checkCapture("/customer/{customerId}", "/customer/78", "customerId", "78");

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/RequestPredicates.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,10 @@ public PathPatternPredicate(PathPattern pattern) {
343343
@Override
344344
public boolean test(ServerRequest request) {
345345
PathContainer pathContainer = request.pathContainer();
346-
boolean match = this.pattern.matches(pathContainer);
347-
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), match);
348-
if (match) {
349-
mergeTemplateVariables(request, this.pattern.matchAndExtract(pathContainer).getUriVariables());
346+
PathPattern.PathMatchInfo info = this.pattern.matchAndExtract(pathContainer);
347+
traceMatch("Pattern", this.pattern.getPatternString(), request.path(), info != null);
348+
if (info != null) {
349+
mergeTemplateVariables(request, info.getUriVariables());
350350
return true;
351351
}
352352
else {

0 commit comments

Comments
 (0)