Browse Source

Rename servletPath to basePath

Closes gh-16765
Josh Cummings 5 months ago
parent
commit
86599afd43

+ 1 - 1
config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java

@@ -1364,7 +1364,7 @@ public class AuthorizeHttpRequestsConfigurerTests {
 
 
 		@Bean
 		@Bean
 		SecurityFilterChain security(HttpSecurity http) throws Exception {
 		SecurityFilterChain security(HttpSecurity http) throws Exception {
-			PathPatternRequestMatcher.Builder mvc = PathPatternRequestMatcher.withDefaults().servletPath("/mvc");
+			PathPatternRequestMatcher.Builder mvc = PathPatternRequestMatcher.withDefaults().basePath("/mvc");
 			// @formatter:off
 			// @formatter:off
 			http
 			http
 				.authorizeHttpRequests((authorize) -> authorize
 				.authorizeHttpRequests((authorize) -> authorize

+ 25 - 18
web/src/main/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcher.java

@@ -166,15 +166,18 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
 	 * a {@link PathPatternRequestMatcher}.
 	 * a {@link PathPatternRequestMatcher}.
 	 *
 	 *
 	 * <p>
 	 * <p>
-	 * For example, if Spring MVC is deployed to `/mvc` and another servlet to `/other`,
-	 * then you can use this builder to do:
-	 * </p>
+	 * To match a request URI like {@code /app/servlet/my/resource/**} where {@code /app}
+	 * is the context path, you can do
+	 * {@code PathPatternRequestMatcher.withDefaults().matcher("/servlet/my/resource/**")}
 	 *
 	 *
-	 * <code>
+	 * <p>
+	 * If you have many paths that have a common path prefix, you can use
+	 * {@link #basePath} to reduce repetition like so: <code>
+	 *     PathPatternRequestMatcher.Builder mvc = withDefaults().basePath("/mvc");
 	 *     http
 	 *     http
 	 *         .authorizeHttpRequests((authorize) -> authorize
 	 *         .authorizeHttpRequests((authorize) -> authorize
-	 *              .requestMatchers(servletPath("/mvc").matcher("/user/**")).hasAuthority("user")
-	 *              .requestMatchers(servletPath("/other").matcher("/admin/**")).hasAuthority("admin")
+	 *              .requestMatchers(mvc.matcher("/user/**")).hasAuthority("user")
+	 *              .requestMatchers(mvc.matcher("/admin/**")).hasAuthority("admin")
 	 *         )
 	 *         )
 	 *             ...
 	 *             ...
 	 * </code>
 	 * </code>
@@ -183,7 +186,7 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
 
 
 		private final PathPatternParser parser;
 		private final PathPatternParser parser;
 
 
-		private final String servletPath;
+		private final String basePath;
 
 
 		Builder() {
 		Builder() {
 			this(PathPatternParser.defaultInstance);
 			this(PathPatternParser.defaultInstance);
@@ -193,22 +196,26 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
 			this(parser, "");
 			this(parser, "");
 		}
 		}
 
 
-		Builder(PathPatternParser parser, String servletPath) {
+		Builder(PathPatternParser parser, String basePath) {
 			this.parser = parser;
 			this.parser = parser;
-			this.servletPath = servletPath;
+			this.basePath = basePath;
 		}
 		}
 
 
 		/**
 		/**
-		 * Match requests starting with this {@code servletPath}.
-		 * @param servletPath the servlet path prefix
+		 * Match requests starting with this {@code basePath}.
+		 *
+		 * <p>
+		 * Prefixes should be of the form {@code /my/prefix}, starting with a slash, not
+		 * ending in a slash, and not containing and wildcards
+		 * @param basePath the path prefix
 		 * @return the {@link Builder} for more configuration
 		 * @return the {@link Builder} for more configuration
 		 */
 		 */
-		public Builder servletPath(String servletPath) {
-			Assert.notNull(servletPath, "servletPath cannot be null");
-			Assert.isTrue(servletPath.startsWith("/"), "servletPath must start with '/'");
-			Assert.isTrue(!servletPath.endsWith("/"), "servletPath must not end with a slash");
-			Assert.isTrue(!servletPath.contains("*"), "servletPath must not contain a star");
-			return new Builder(this.parser, servletPath);
+		public Builder basePath(String basePath) {
+			Assert.notNull(basePath, "basePath cannot be null");
+			Assert.isTrue(basePath.startsWith("/"), "basePath must start with '/'");
+			Assert.isTrue(!basePath.endsWith("/"), "basePath must not end with a slash");
+			Assert.isTrue(!basePath.contains("*"), "basePath must not contain a star");
+			return new Builder(this.parser, basePath);
 		}
 		}
 
 
 		/**
 		/**
@@ -279,7 +286,7 @@ public final class PathPatternRequestMatcher implements RequestMatcher {
 		public PathPatternRequestMatcher matcher(@Nullable HttpMethod method, String path) {
 		public PathPatternRequestMatcher matcher(@Nullable HttpMethod method, String path) {
 			Assert.notNull(path, "pattern cannot be null");
 			Assert.notNull(path, "pattern cannot be null");
 			Assert.isTrue(path.startsWith("/"), "pattern must start with a /");
 			Assert.isTrue(path.startsWith("/"), "pattern must start with a /");
-			PathPattern pathPattern = this.parser.parse(this.servletPath + path);
+			PathPattern pathPattern = this.parser.parse(this.basePath + path);
 			PathPatternRequestMatcher requestMatcher = new PathPatternRequestMatcher(pathPattern);
 			PathPatternRequestMatcher requestMatcher = new PathPatternRequestMatcher(pathPattern);
 			if (method != null) {
 			if (method != null) {
 				requestMatcher.setMethod(new HttpMethodRequestMatcher(method));
 				requestMatcher.setMethod(new HttpMethodRequestMatcher(method));

+ 6 - 9
web/src/test/java/org/springframework/security/web/servlet/util/matcher/PathPatternRequestMatcherTests.java

@@ -87,8 +87,7 @@ public class PathPatternRequestMatcherTests {
 
 
 	@Test
 	@Test
 	void matcherWhenServletPathThenMatchesOnlyServletPath() {
 	void matcherWhenServletPathThenMatchesOnlyServletPath() {
-		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults()
-			.servletPath("/servlet/path");
+		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults().basePath("/servlet/path");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		ServletContext servletContext = servletContext("/servlet/path");
 		ServletContext servletContext = servletContext("/servlet/path");
 		MockHttpServletRequest mock = get("/servlet/path/endpoint").servletPath("/servlet/path")
 		MockHttpServletRequest mock = get("/servlet/path/endpoint").servletPath("/servlet/path")
@@ -114,8 +113,7 @@ public class PathPatternRequestMatcherTests {
 
 
 	@Test
 	@Test
 	void matcherWhenMultiServletPathThenMatches() {
 	void matcherWhenMultiServletPathThenMatches() {
-		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults()
-			.servletPath("/servlet/path");
+		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults().basePath("/servlet/path");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		MockHttpServletRequest mock = get("/servlet/path/endpoint").servletPath("/servlet/path").buildRequest(null);
 		MockHttpServletRequest mock = get("/servlet/path/endpoint").servletPath("/servlet/path").buildRequest(null);
 		assertThat(matcher.matches(mock)).isTrue();
 		assertThat(matcher.matches(mock)).isTrue();
@@ -123,8 +121,7 @@ public class PathPatternRequestMatcherTests {
 
 
 	@Test
 	@Test
 	void matcherWhenMultiContextPathThenMatches() {
 	void matcherWhenMultiContextPathThenMatches() {
-		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults()
-			.servletPath("/servlet/path");
+		PathPatternRequestMatcher.Builder servlet = PathPatternRequestMatcher.withDefaults().basePath("/servlet/path");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		RequestMatcher matcher = servlet.matcher(HttpMethod.GET, "/endpoint");
 		assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> matcher.matches(
 		assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> matcher.matches(
 				get("/servlet/path/endpoint").servletPath("/servlet/path").contextPath("/app").buildRequest(null)));
 				get("/servlet/path/endpoint").servletPath("/servlet/path").contextPath("/app").buildRequest(null)));
@@ -133,11 +130,11 @@ public class PathPatternRequestMatcherTests {
 	@Test
 	@Test
 	void servletPathWhenEndsWithSlashOrStarThenIllegalArgument() {
 	void servletPathWhenEndsWithSlashOrStarThenIllegalArgument() {
 		assertThatExceptionOfType(IllegalArgumentException.class)
 		assertThatExceptionOfType(IllegalArgumentException.class)
-			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().servletPath("/path/**"));
+			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().basePath("/path/**"));
 		assertThatExceptionOfType(IllegalArgumentException.class)
 		assertThatExceptionOfType(IllegalArgumentException.class)
-			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().servletPath("/path/*"));
+			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().basePath("/path/*"));
 		assertThatExceptionOfType(IllegalArgumentException.class)
 		assertThatExceptionOfType(IllegalArgumentException.class)
-			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().servletPath("/path/"));
+			.isThrownBy(() -> PathPatternRequestMatcher.withDefaults().basePath("/path/"));
 	}
 	}
 
 
 	MockHttpServletRequest request(String uri) {
 	MockHttpServletRequest request(String uri) {