Support for parsed PathPatterns in Spring MVC

See gh-24945
This commit is contained in:
Rossen Stoyanchev
2020-06-15 11:20:32 +01:00
parent a0f4d81db7
commit 5225a57411
82 changed files with 5324 additions and 3011 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.http.server;
import java.net.URI;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -25,10 +23,10 @@ import static org.assertj.core.api.Assertions.assertThat;
* Unit tests for {@link DefaultRequestPath}.
* @author Rossen Stoyanchev
*/
public class DefaultRequestPathTests {
class DefaultRequestPathTests {
@Test
public void requestPath() throws Exception {
void requestPath() {
// basic
testRequestPath("/app/a/b/c", "/app", "/a/b/c");
@@ -52,8 +50,7 @@ public class DefaultRequestPathTests {
private void testRequestPath(String fullPath, String contextPath, String pathWithinApplication) {
URI uri = URI.create("http://localhost:8080" + fullPath);
RequestPath requestPath = RequestPath.parse(uri, contextPath);
RequestPath requestPath = RequestPath.parse(fullPath, contextPath);
Object expected = contextPath.equals("/") ? "" : contextPath;
assertThat(requestPath.contextPath().value()).isEqualTo(expected);
@@ -61,10 +58,9 @@ public class DefaultRequestPathTests {
}
@Test
public void updateRequestPath() throws Exception {
void updateRequestPath() {
URI uri = URI.create("http://localhost:8080/aA/bB/cC");
RequestPath requestPath = RequestPath.parse(uri, null);
RequestPath requestPath = RequestPath.parse("/aA/bB/cC", null);
assertThat(requestPath.contextPath().value()).isEqualTo("");
assertThat(requestPath.pathWithinApplication().value()).isEqualTo("/aA/bB/cC");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,44 +16,96 @@
package org.springframework.web.cors;
import org.junit.jupiter.api.Test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.http.HttpMethod;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import org.springframework.web.util.ServletRequestPathUtils;
import org.springframework.web.util.UrlPathHelper;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Unit tests for {@link UrlBasedCorsConfigurationSource}.
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
public class UrlBasedCorsConfigurationSourceTests {
class UrlBasedCorsConfigurationSourceTests {
private final UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
@Test
public void empty() {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "/bar/test.html");
assertThat(this.configSource.getCorsConfiguration(request)).isNull();
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ParameterizedTest
@MethodSource("pathPatternsArguments")
@interface PathPatternsParameterizedTest {
}
@Test
public void registerAndMatch() {
@SuppressWarnings("unused")
private static Stream<Function<String, MockHttpServletRequest>> pathPatternsArguments() {
return Stream.of(
requestUri -> {
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
ServletRequestPathUtils.parseAndCache(request);
return request;
},
requestUri -> {
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
UrlPathHelper.defaultInstance.getLookupPathForRequest(request);
return request;
}
);
}
@PathPatternsParameterizedTest
void empty(Function<String, MockHttpServletRequest> requestFactory) {
CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
assertThat(source.getCorsConfiguration(requestFactory.apply("/bar/test.html"))).isNull();
}
@PathPatternsParameterizedTest
void registerAndMatch(Function<String, MockHttpServletRequest> requestFactory) {
CorsConfiguration config = new CorsConfiguration();
this.configSource.registerCorsConfiguration("/bar/**", config);
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/bar/**", config);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/test.html");
assertThat(this.configSource.getCorsConfiguration(request)).isNull();
MockHttpServletRequest request = requestFactory.apply("/foo/test.html");
assertThat(configSource.getCorsConfiguration(request)).isNull();
request.setRequestURI("/bar/test.html");
assertThat(this.configSource.getCorsConfiguration(request)).isEqualTo(config);
request = requestFactory.apply("/bar/test.html");
assertThat(configSource.getCorsConfiguration(request)).isEqualTo(config);
}
@Test
public void unmodifiableConfigurationsMap() {
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
this.configSource.getCorsConfigurations().put("/**", new CorsConfiguration()));
void unmodifiableConfigurationsMap() {
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.getCorsConfigurations().put("/**", new CorsConfiguration());
});
}
@Test
void allowInitLookupPath() {
CorsConfiguration config = new CorsConfiguration();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
assertThat(source.getCorsConfiguration(request))
.as("The path should be resolved lazily by default")
.isSameAs(config);
source.setAllowInitLookupPath(false);
assertThatIllegalArgumentException().isThrownBy(() -> source.getCorsConfiguration(request));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,20 +30,20 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
public class UrlBasedCorsConfigurationSourceTests {
class UrlBasedCorsConfigurationSourceTests {
private final UrlBasedCorsConfigurationSource configSource
= new UrlBasedCorsConfigurationSource();
@Test
public void empty() {
void empty() {
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/bar/test.html"));
assertThat(this.configSource.getCorsConfiguration(exchange)).isNull();
}
@Test
public void registerAndMatch() {
void registerAndMatch() {
CorsConfiguration config = new CorsConfiguration();
this.configSource.registerCorsConfiguration("/bar/**", config);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
@@ -44,19 +45,24 @@ public class CorsFilterTests {
private final CorsConfiguration config = new CorsConfiguration();
@BeforeEach
public void setup() throws Exception {
void setup() {
config.setAllowedOrigins(Arrays.asList("https://domain1.com", "https://domain2.com"));
config.setAllowedMethods(Arrays.asList("GET", "POST"));
config.setAllowedHeaders(Arrays.asList("header1", "header2"));
config.setExposedHeaders(Arrays.asList("header3", "header4"));
config.setMaxAge(123L);
config.setAllowCredentials(false);
filter = new CorsFilter(r -> config);
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
filter = new CorsFilter(configSource);
}
@Test
public void nonCorsRequest() throws ServletException, IOException {
void nonCorsRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "/test.html");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -69,7 +75,7 @@ public class CorsFilterTests {
}
@Test
public void sameOriginRequest() throws ServletException, IOException {
void sameOriginRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "https://domain1.com/test.html");
request.addHeader(HttpHeaders.ORIGIN, "https://domain1.com");
@@ -86,7 +92,7 @@ public class CorsFilterTests {
}
@Test
public void validActualRequest() throws ServletException, IOException {
void validActualRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.GET.name(), "/test.html");
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
@@ -101,7 +107,7 @@ public class CorsFilterTests {
}
@Test
public void invalidActualRequest() throws ServletException, IOException {
void invalidActualRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.DELETE.name(), "/test.html");
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
@@ -115,7 +121,7 @@ public class CorsFilterTests {
}
@Test
public void validPreFlightRequest() throws ServletException, IOException {
void validPreFlightRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.OPTIONS.name(), "/test.html");
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");
@@ -134,7 +140,7 @@ public class CorsFilterTests {
}
@Test
public void invalidPreFlightRequest() throws ServletException, IOException {
void invalidPreFlightRequest() throws ServletException, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(HttpMethod.OPTIONS.name(), "/test.html");
request.addHeader(HttpHeaders.ORIGIN, "https://domain2.com");