Skip to content

Commit eb22c9b

Browse files
committed
Respond to Feedback
1 parent 0899253 commit eb22c9b

File tree

3 files changed

+61
-44
lines changed

3 files changed

+61
-44
lines changed

docs/modules/ROOT/pages/migration/web.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Java::
1515
[source,java,role="primary"]
1616
----
1717
@Bean
18-
MethodPatternRequestMatcherFactory requestMatcherFactory() {
19-
return PathPatternRequestMatcher.path();
18+
MethodPatternRequestMatcherFactory requestMatcherFactory(@Qualifier("mvcPatternParser") PathPatternParser parser) {
19+
return PathPatternRequestMatcher.withPathPatternParser(parser);
2020
}
2121
----
2222
@@ -25,8 +25,8 @@ Kotlin::
2525
[source,kotlin,role="secondary"]
2626
----
2727
@Bean
28-
fun requestMatcherFactory(): MethodPatternRequestMatcherFactory {
29-
return PathPatternRequestMatcher.path()
28+
fun requestMatcherFactory(@Qualifier("mvcPatternParser") parser: PathPatternParser): MethodPatternRequestMatcherFactory {
29+
return PathPatternRequestMatcher.withPathPatternParser(parser)
3030
}
3131
----
3232
======

web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,15 @@
1616

1717
package org.springframework.security.web.servlet.util.matcher;
1818

19-
import java.nio.charset.StandardCharsets;
2019
import java.util.Collection;
2120
import java.util.LinkedHashMap;
2221
import java.util.Map;
2322
import java.util.Objects;
2423
import java.util.concurrent.atomic.AtomicReference;
2524

26-
import jakarta.servlet.RequestDispatcher;
2725
import jakarta.servlet.ServletContext;
2826
import jakarta.servlet.ServletRegistration;
29-
import jakarta.servlet.http.HttpServletMapping;
3027
import jakarta.servlet.http.HttpServletRequest;
31-
import jakarta.servlet.http.MappingMatch;
3228

3329
import org.springframework.http.HttpMethod;
3430
import org.springframework.http.server.PathContainer;
@@ -39,10 +35,7 @@
3935
import org.springframework.security.web.util.matcher.MethodPatternRequestMatcherFactory;
4036
import org.springframework.security.web.util.matcher.RequestMatcher;
4137
import org.springframework.util.Assert;
42-
import org.springframework.util.ObjectUtils;
4338
import org.springframework.web.util.ServletRequestPathUtils;
44-
import org.springframework.web.util.UriUtils;
45-
import org.springframework.web.util.WebUtils;
4639
import org.springframework.web.util.pattern.PathPattern;
4740
import org.springframework.web.util.pattern.PathPatternParser;
4841

@@ -88,9 +81,7 @@ private PathPatternRequestMatcher(PathPattern pattern) {
8881
* prefix
8982
* <p>
9083
* When there is no context path, then these URIs are effectively absolute.
91-
* @return a {@link PathPatternRequestMatcher.Builder} that treats URIs as relative to
92-
* the context path, if any
93-
* @since 6.5
84+
* @return a {@link Builder} that treats URIs as relative to the context path, if any
9485
*/
9586
public static Builder path() {
9687
return new Builder();
@@ -109,17 +100,25 @@ public static Builder path() {
109100
* {@link HttpServletRequest#getServletPath()} would return {@code /path} and so
110101
* {@code /path} is what is specified here.
111102
*
103+
* <p>
112104
* Specify the path here without the trailing {@code /*}.
113-
* @return a {@link PathPatternRequestMatcher.Builder} that treats URIs as relative to
114-
* the given {@code servletPath}
115-
* @since 6.5
105+
* @return a {@link Builder} that treats URIs as relative to the given
106+
* {@code servletPath}
116107
*/
117108
public static Builder servletPath(String servletPath) {
118-
Assert.notNull(servletPath, "servletPath cannot be null");
119-
Assert.isTrue(servletPath.startsWith("/"), "servletPath must start with '/'");
120-
Assert.isTrue(!servletPath.endsWith("/"), "servletPath must not end with a slash");
121-
Assert.isTrue(!servletPath.contains("*"), "servletPath must not contain a star");
122-
return new Builder(new ServletPathRequestMatcher(servletPath));
109+
return new Builder().servletPath(servletPath);
110+
}
111+
112+
/**
113+
* Use this {@link PathPatternParser} to parse path patterns. Uses
114+
* {@link PathPatternParser#defaultInstance} by default.
115+
* @param parser the {@link PathPatternParser} to use
116+
* @return a {@link Builder} that treats URIs as relative to the given
117+
* {@code servletPath}
118+
*/
119+
public static Builder withPathPatternParser(PathPatternParser parser) {
120+
Assert.notNull(parser, "pathPatternParser cannot be null");
121+
return new Builder(parser);
123122
}
124123

125124
/**
@@ -212,16 +211,27 @@ public String toString() {
212211
*/
213212
public static final class Builder implements MethodPatternRequestMatcherFactory {
214213

215-
private PathPatternParser parser = PathPatternParser.defaultInstance;
214+
private final PathPatternParser parser;
216215

217-
private final RequestMatcher servletPath;
216+
private RequestMatcher servletPath = AnyRequestMatcher.INSTANCE;
218217

219-
Builder() {
220-
this(AnyRequestMatcher.INSTANCE);
218+
private Builder() {
219+
this.parser = PathPatternParser.defaultInstance;
221220
}
222221

223-
Builder(RequestMatcher servletPath) {
224-
this.servletPath = servletPath;
222+
private Builder(PathPatternParser parser) {
223+
this.parser = parser;
224+
}
225+
226+
/**
227+
* Match requests starting with this {@code servletPath}.
228+
* @param servletPath the servlet path prefix
229+
* @see PathPatternRequestMatcher#servletPath
230+
* @return the {@link Builder} for more configuration
231+
*/
232+
public Builder servletPath(String servletPath) {
233+
this.servletPath = new ServletPathRequestMatcher(servletPath);
234+
return this;
225235
}
226236

227237
/**
@@ -298,14 +308,18 @@ private static final class ServletPathRequestMatcher implements RequestMatcher {
298308
private final AtomicReference<Boolean> servletExists = new AtomicReference<>();
299309

300310
ServletPathRequestMatcher(String servletPath) {
311+
Assert.notNull(servletPath, "servletPath cannot be null");
312+
Assert.isTrue(servletPath.startsWith("/"), "servletPath must start with '/'");
313+
Assert.isTrue(!servletPath.endsWith("/"), "servletPath must not end with a slash");
314+
Assert.isTrue(!servletPath.contains("*"), "servletPath must not contain a star");
301315
this.path = servletPath;
302316
}
303317

304318
@Override
305319
public boolean matches(HttpServletRequest request) {
306320
Assert.isTrue(servletExists(request), () -> this.path + "/* does not exist in your servlet registration "
307321
+ registrationMappings(request));
308-
return Objects.equals(this.path, getServletPathPrefix(request));
322+
return Objects.equals(this.path, ServletRequestPathUtils.getServletPathPrefix(request));
309323
}
310324

311325
private boolean servletExists(HttpServletRequest request) {
@@ -336,20 +350,6 @@ private Map<String, Collection<String>> registrationMappings(HttpServletRequest
336350
return map;
337351
}
338352

339-
@Nullable
340-
private static String getServletPathPrefix(HttpServletRequest request) {
341-
HttpServletMapping mapping = (HttpServletMapping) request.getAttribute(RequestDispatcher.INCLUDE_MAPPING);
342-
mapping = (mapping != null) ? mapping : request.getHttpServletMapping();
343-
if (ObjectUtils.nullSafeEquals(mapping.getMappingMatch(), MappingMatch.PATH)) {
344-
String servletPath = (String) request.getAttribute(WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE);
345-
servletPath = (servletPath != null) ? servletPath : request.getServletPath();
346-
servletPath = servletPath.endsWith("/") ? servletPath.substring(0, servletPath.length() - 1)
347-
: servletPath;
348-
return UriUtils.encodePath(servletPath, StandardCharsets.UTF_8);
349-
}
350-
return null;
351-
}
352-
353353
@Override
354354
public String toString() {
355355
return "ServletPath [" + this.path + "]";

web/src/main/java/org/springframework/security/web/util/matcher/MethodPatternRequestMatcherFactory.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.security.web.util.matcher;
1818

1919
import org.springframework.http.HttpMethod;
20+
import org.springframework.lang.Nullable;
2021

2122
/**
2223
* A strategy for constructing request matchers that match method-path pairs
@@ -26,10 +27,26 @@
2627
*/
2728
public interface MethodPatternRequestMatcherFactory {
2829

30+
/**
31+
* Request a method-pattern request matcher given the following {{@code method} and
32+
* {@code pattern}.
33+
* This method in this case is treated as a wildcard.
34+
*
35+
* @param pattern the path pattern to use
36+
* @return the {@link RequestMatcher}
37+
*/
2938
default RequestMatcher matcher(String pattern) {
3039
return matcher(null, pattern);
3140
}
3241

33-
RequestMatcher matcher(HttpMethod method, String pattern);
42+
/**
43+
* Request a method-pattern request matcher given the following
44+
* {@code method} and {@code pattern}.
45+
*
46+
* @param method the method to use, may be null
47+
* @param pattern the path pattern to use
48+
* @return the {@link RequestMatcher}
49+
*/
50+
RequestMatcher matcher(@Nullable HttpMethod method, String pattern);
3451

3552
}

0 commit comments

Comments
 (0)