diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java
index eb0bf1534e..94a745e970 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistration.java
@@ -24,20 +24,16 @@ import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.cors.CorsConfiguration;
/**
- * {@code CorsRegistration} assists with the creation of a
- * {@link CorsConfiguration} instance mapped to a path pattern.
+ * Assists with the creation of a {@link CorsConfiguration} instance mapped to
+ * a path pattern.
*
- *
If no path pattern is specified, cross-origin request handling is
- * mapped to {@code "/**"}.
- *
- *
By default, all origins, all headers, credentials and {@code GET},
- * {@code HEAD}, and {@code POST} methods are allowed, and the max age is
- * set to 30 minutes.
+ *
If no path pattern is specified, by default cross-origin request handling
+ * is mapped to {@code "/**"}. Also by default, all origins, headers,
+ * credentials and {@code GET}, {@code HEAD}, and {@code POST} methods are
+ * allowed, while the max age is set to 30 minutes.
*
* @author Sebastien Deleuze
- * @author Sam Brannen
* @since 5.0
- * @see CorsConfiguration
* @see CorsRegistry
*/
public class CorsRegistration {
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistry.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistry.java
index f7f11e7a1d..67b3a06d33 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistry.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/CorsRegistry.java
@@ -58,4 +58,5 @@ public class CorsRegistry {
}
return configs;
}
+
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java
index 2a92ab463a..a67215de55 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java
@@ -45,6 +45,8 @@ import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.HttpMessageWriter;
+import org.springframework.http.codec.Jackson2ServerHttpMessageReader;
+import org.springframework.http.codec.Jackson2ServerHttpMessageWriter;
import org.springframework.http.codec.ResourceHttpMessageWriter;
import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
@@ -61,8 +63,6 @@ import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuild
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
-import org.springframework.http.codec.Jackson2ServerHttpMessageReader;
-import org.springframework.http.codec.Jackson2ServerHttpMessageWriter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler;
@@ -90,14 +90,14 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
ClassUtils.isPresent("javax.xml.bind.Binder", WebReactiveConfiguration.class.getClassLoader());
+ private Map corsConfigurations;
+
private PathMatchConfigurer pathMatchConfigurer;
private List> messageReaders;
private List> messageWriters;
- private Map corsConfigurations;
-
private ApplicationContext applicationContext;
@@ -171,6 +171,26 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
protected void configureRequestedContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
}
+ /**
+ * Callback for building the global CORS configuration. This method is final.
+ * Use {@link #addCorsMappings(CorsRegistry)} to customize the CORS conifg.
+ */
+ protected final Map getCorsConfigurations() {
+ if (this.corsConfigurations == null) {
+ CorsRegistry registry = new CorsRegistry();
+ addCorsMappings(registry);
+ this.corsConfigurations = registry.getCorsConfigurations();
+ }
+ return this.corsConfigurations;
+ }
+
+ /**
+ * Override this method to configure cross origin requests processing.
+ * @see CorsRegistry
+ */
+ protected void addCorsMappings(CorsRegistry registry) {
+ }
+
/**
* Callback for building the {@link PathMatchConfigurer}. This method is
* final, use {@link #configurePathMatching} to customize path matching.
@@ -209,6 +229,7 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
if (pathMatchConfigurer.getPathHelper() != null) {
handlerMapping.setPathHelper(pathMatchConfigurer.getPathHelper());
}
+
}
else {
handlerMapping = new EmptyHandlerMapping();
@@ -444,22 +465,6 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
protected void configureViewResolvers(ViewResolverRegistry registry) {
}
- protected final Map getCorsConfigurations() {
- if (this.corsConfigurations == null) {
- CorsRegistry registry = new CorsRegistry();
- addCorsMappings(registry);
- this.corsConfigurations = registry.getCorsConfigurations();
- }
- return this.corsConfigurations;
- }
-
- /**
- * Override this method to configure cross origin requests processing.
- * @see CorsRegistry
- */
- protected void addCorsMappings(CorsRegistry registry) {
- }
-
private static final class EmptyHandlerMapping extends AbstractHandlerMapping {
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java
index b009b23cc7..680d20a48f 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractHandlerMapping.java
@@ -51,9 +51,10 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
private PathMatcher pathMatcher = new AntPathMatcher();
- protected CorsProcessor corsProcessor = new DefaultCorsProcessor();
+ private final UrlBasedCorsConfigurationSource globalCorsConfigSource = new UrlBasedCorsConfigurationSource();
+
+ private CorsProcessor corsProcessor = new DefaultCorsProcessor();
- protected final UrlBasedCorsConfigurationSource corsConfigSource = new UrlBasedCorsConfigurationSource();
/**
* Specify the order value for this HandlerMapping bean.
@@ -104,7 +105,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
public void setPathMatcher(PathMatcher pathMatcher) {
Assert.notNull(pathMatcher, "PathMatcher must not be null");
this.pathMatcher = pathMatcher;
- this.corsConfigSource.setPathMatcher(pathMatcher);
+ this.globalCorsConfigSource.setPathMatcher(pathMatcher);
}
/**
@@ -115,9 +116,26 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
return this.pathMatcher;
}
+ /**
+ * Set "global" CORS configuration based on URL patterns. By default the
+ * first matching URL pattern is combined with handler-level CORS
+ * configuration if any.
+ */
+ public void setCorsConfigurations(Map corsConfigurations) {
+ this.globalCorsConfigSource.setCorsConfigurations(corsConfigurations);
+ }
+
+ /**
+ * Return the "global" CORS configuration.
+ */
+ public Map getCorsConfigurations() {
+ return this.globalCorsConfigSource.getCorsConfigurations();
+ }
+
/**
* Configure a custom {@link CorsProcessor} to use to apply the matched
- * {@link CorsConfiguration} for a request. By default {@link DefaultCorsProcessor} is used.
+ * {@link CorsConfiguration} for a request.
+ * By default an instance of {@link DefaultCorsProcessor} is used.
*/
public void setCorsProcessor(CorsProcessor corsProcessor) {
Assert.notNull(corsProcessor, "CorsProcessor must not be null");
@@ -131,22 +149,27 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
return this.corsProcessor;
}
- /**
- * Set "global" CORS configuration based on URL patterns. By default the first
- * matching URL pattern is combined with the CORS configuration for the
- * handler, if any.
- */
- public void setCorsConfigurations(Map corsConfigurations) {
- this.corsConfigSource.setCorsConfigurations(corsConfigurations);
+
+ protected Object processCorsRequest(ServerWebExchange exchange, Object handler) {
+ if (CorsUtils.isCorsRequest(exchange.getRequest())) {
+ CorsConfiguration configA = this.globalCorsConfigSource.getCorsConfiguration(exchange);
+ CorsConfiguration configB = getCorsConfiguration(handler, exchange);
+ CorsConfiguration config = (configA != null ? configA.combine(configB) : configB);
+
+ if (!getCorsProcessor().processRequest(config, exchange) ||
+ CorsUtils.isPreFlightRequest(exchange.getRequest())) {
+ return REQUEST_HANDLED_HANDLER;
+ }
+ }
+ return handler;
}
/**
- * Get the CORS configuration.
+ * Retrieve the CORS configuration for the given handler.
+ * @param handler the handler to check (never {@code null}).
+ * @param exchange the current exchange
+ * @return the CORS configuration for the handler or {@code null}.
*/
- public Map getCorsConfigurations() {
- return this.corsConfigSource.getCorsConfigurations();
- }
-
protected CorsConfiguration getCorsConfiguration(Object handler, ServerWebExchange exchange) {
if (handler != null && handler instanceof CorsConfigurationSource) {
return ((CorsConfigurationSource) handler).getCorsConfiguration(exchange);
@@ -154,23 +177,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
return null;
}
- protected Object processCorsRequest(ServerWebExchange exchange, Object handler) {
- if (CorsUtils.isCorsRequest(exchange.getRequest())) {
- CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(exchange);
- CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);
- CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
- if (!corsProcessor.processRequest(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) {
- return new NoOpHandler();
- }
- }
- return handler;
- }
- private class NoOpHandler implements WebHandler {
- @Override
- public Mono handle(ServerWebExchange exchange) {
- return Mono.empty();
- }
- }
+ private static final WebHandler REQUEST_HANDLED_HANDLER = exchange -> Mono.empty();
-}
+}
\ No newline at end of file
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractUrlHandlerMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractUrlHandlerMapping.java
index bb87cee707..f4ec65af55 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractUrlHandlerMapping.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/handler/AbstractUrlHandlerMapping.java
@@ -98,7 +98,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
@Override
public Mono getHandler(ServerWebExchange exchange) {
String lookupPath = getPathHelper().getLookupPathForRequest(exchange);
- Object handler = null;
+ Object handler;
try {
handler = lookupHandler(lookupPath, exchange);
handler = processCorsRequest(exchange, handler);
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java
index 063e5fc3bc..312b7d69ac 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java
@@ -29,14 +29,11 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import javax.servlet.http.HttpServletRequest;
-
import reactor.core.publisher.Mono;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.MethodIntrospector;
-import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
@@ -75,8 +72,13 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap
*/
private static final String SCOPED_TARGET_NAME_PREFIX = "scopedTarget.";
+ /**
+ * HandlerMethod to return on a pre-flight request match when the request
+ * mappings are more nuanced than the access control headers.
+ */
private static final HandlerMethod PREFLIGHT_AMBIGUOUS_MATCH =
- new HandlerMethod(new EmptyHandler(), ClassUtils.getMethod(EmptyHandler.class, "handle"));
+ new HandlerMethod(new PreFlightAmbiguousMatchHandler(),
+ ClassUtils.getMethod(PreFlightAmbiguousMatchHandler.class, "handle"));
private static final CorsConfiguration ALLOW_CORS_CONFIG = new CorsConfiguration();
@@ -372,12 +374,10 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
if (handlerMethod.equals(PREFLIGHT_AMBIGUOUS_MATCH)) {
- return AbstractHandlerMethodMapping.ALLOW_CORS_CONFIG;
- }
- else {
- CorsConfiguration corsConfigFromMethod = this.mappingRegistry.getCorsConfiguration(handlerMethod);
- corsConfig = (corsConfig != null ? corsConfig.combine(corsConfigFromMethod) : corsConfigFromMethod);
+ return ALLOW_CORS_CONFIG;
}
+ CorsConfiguration methodConfig = this.mappingRegistry.getCorsConfiguration(handlerMethod);
+ corsConfig = (corsConfig != null ? corsConfig.combine(methodConfig) : methodConfig);
}
return corsConfig;
}
@@ -625,7 +625,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap
}
}
- private static class EmptyHandler {
+ private static class PreFlightAmbiguousMatchHandler {
public void handle() {
throw new UnsupportedOperationException("not implemented");
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java
index e87cf47855..439a5c78b9 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.java
@@ -282,7 +282,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@Override
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
- CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
+ Class> beanType = handlerMethod.getBeanType();
+ CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
if (typeAnnotation == null && methodAnnotation == null) {
@@ -310,6 +311,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
if (config.getMaxAge() == null) {
config.setMaxAge(CrossOrigin.DEFAULT_MAX_AGE);
}
+
return config;
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsAbstractUrlHandlerMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsUrlHandlerMappingTests.java
similarity index 55%
rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsAbstractUrlHandlerMappingTests.java
rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsUrlHandlerMappingTests.java
index 3ed1bc6efc..05f0ad92aa 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsAbstractUrlHandlerMappingTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/handler/CorsUrlHandlerMappingTests.java
@@ -15,7 +15,6 @@
*/
package org.springframework.web.reactive.handler;
-import java.net.URISyntaxException;
import java.util.Collections;
import static org.junit.Assert.*;
@@ -23,9 +22,6 @@ import static org.junit.Assert.assertSame;
import org.junit.Before;
import org.junit.Test;
-import org.springframework.context.annotation.AnnotationConfigApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -44,132 +40,111 @@ import org.springframework.web.server.session.WebSessionManager;
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
-public class CorsAbstractUrlHandlerMappingTests {
+public class CorsUrlHandlerMappingTests {
- private AnnotationConfigApplicationContext wac;
+ private AbstractUrlHandlerMapping handlerMapping;
- private TestUrlHandlerMapping handlerMapping;
+ private Object welcomeController = new Object();
- private Object mainController;
+ private CorsAwareHandler corsController = new CorsAwareHandler();
- private CorsAwareHandler corsConfigurationSourceController;
@Before
public void setup() {
- wac = new AnnotationConfigApplicationContext();
- wac.register(WebConfig.class);
- wac.refresh();
-
- handlerMapping = (TestUrlHandlerMapping) wac.getBean("handlerMapping");
- mainController = wac.getBean("mainController");
- corsConfigurationSourceController = (CorsAwareHandler) wac.getBean("corsConfigurationSourceController");
+ this.handlerMapping = new AbstractUrlHandlerMapping() {};
+ this.handlerMapping.setUseTrailingSlashMatch(true);
+ this.handlerMapping.registerHandler("/welcome.html", this.welcomeController);
+ this.handlerMapping.registerHandler("/cors.html", this.corsController);
}
+
@Test
public void actualRequestWithoutCorsConfigurationProvider() throws Exception {
- ServerWebExchange exchange = createExchange(HttpMethod.GET, "/welcome.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.GET, "/welcome.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertSame(mainController, actual);
+ assertSame(this.welcomeController, actual);
}
@Test
public void preflightRequestWithoutCorsConfigurationProvider() throws Exception {
- ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/welcome.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/welcome.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertEquals("NoOpHandler", actual.getClass().getSimpleName());
+ assertNotSame(this.welcomeController, actual);
assertNull(exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
@Test
- public void actualRequestWithCorsConfigurationProvider() throws Exception {
- ServerWebExchange exchange = createExchange(HttpMethod.GET, "/cors.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ public void actualRequestWithCorsAwareHandler() throws Exception {
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.GET, "/cors.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertSame(corsConfigurationSourceController, actual);
- CorsConfiguration config = ((CorsConfigurationSource)actual).getCorsConfiguration(createExchange(HttpMethod.GET, "", "",""));
- assertNotNull(config);
- assertArrayEquals(config.getAllowedOrigins().toArray(), new String[]{"*"});
+ assertSame(this.corsController, actual);
assertEquals("*", exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
@Test
- public void preflightRequestWithCorsConfigurationProvider() throws Exception {
- ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/cors.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ public void preFlightWithCorsAwareHandler() throws Exception {
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/cors.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertEquals("NoOpHandler", actual.getClass().getSimpleName());
+ assertNotSame(this.corsController, actual);
assertEquals("*", exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
@Test
- public void actualRequestWithMappedCorsConfiguration() throws Exception {
+ public void actualRequestWithGlobalCorsConfig() throws Exception {
CorsConfiguration mappedConfig = new CorsConfiguration();
mappedConfig.addAllowedOrigin("*");
this.handlerMapping.setCorsConfigurations(Collections.singletonMap("/welcome.html", mappedConfig));
- ServerWebExchange exchange = createExchange(HttpMethod.GET, "/welcome.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.GET, "/welcome.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertSame(mainController, actual);
+ assertSame(this.welcomeController, actual);
assertEquals("*", exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
@Test
- public void preflightRequestWithMappedCorsConfiguration() throws Exception {
+ public void preFlightRequestWithGlobalCorsConfig() throws Exception {
CorsConfiguration mappedConfig = new CorsConfiguration();
mappedConfig.addAllowedOrigin("*");
this.handlerMapping.setCorsConfigurations(Collections.singletonMap("/welcome.html", mappedConfig));
- ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/welcome.html", "http://domain2.com", "GET");
- Object actual = handlerMapping.getHandler(exchange).block();
+ String origin = "http://domain2.com";
+ ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/welcome.html", origin, "GET");
+ Object actual = this.handlerMapping.getHandler(exchange).block();
+
assertNotNull(actual);
- assertEquals("NoOpHandler", actual.getClass().getSimpleName());
+ assertNotSame(this.welcomeController, actual);
assertEquals("*", exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
private ServerWebExchange createExchange(HttpMethod method, String path, String origin,
- String accessControlRequestMethod) throws URISyntaxException {
+ String accessControlRequestMethod) {
ServerHttpRequest request = new MockServerHttpRequest(method, "http://localhost" + path);
request.getHeaders().add(HttpHeaders.ORIGIN, origin);
request.getHeaders().add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, accessControlRequestMethod);
+ MockServerHttpResponse response = new MockServerHttpResponse();
WebSessionManager sessionManager = new MockWebSessionManager();
- return new DefaultServerWebExchange(request, new MockServerHttpResponse(), sessionManager);
+ return new DefaultServerWebExchange(request, response, sessionManager);
}
- @Configuration
- static class WebConfig {
-
- @Bean @SuppressWarnings("unused")
- public TestUrlHandlerMapping handlerMapping() {
- TestUrlHandlerMapping hm = new TestUrlHandlerMapping();
- hm.setUseTrailingSlashMatch(true);
- hm.registerHandler("/welcome.html", mainController());
- hm.registerHandler("/cors.html", corsConfigurationSourceController());
- return hm;
- }
-
- @Bean
- public Object mainController() {
- return new Object();
- }
-
- @Bean
- public CorsAwareHandler corsConfigurationSourceController() {
- return new CorsAwareHandler();
- }
-
- }
-
- static class TestUrlHandlerMapping extends AbstractUrlHandlerMapping {
-
- }
-
- static class CorsAwareHandler implements CorsConfigurationSource {
+ private class CorsAwareHandler implements CorsConfigurationSource {
@Override
public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/AbstractRequestMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/AbstractRequestMappingIntegrationTests.java
index b2aa35a3bf..e6f373a9de 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/AbstractRequestMappingIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/AbstractRequestMappingIntegrationTests.java
@@ -16,9 +16,13 @@
package org.springframework.web.reactive.result.method.annotation;
import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
import org.springframework.context.ApplicationContext;
import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
@@ -30,20 +34,24 @@ import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
import static org.springframework.http.RequestEntity.get;
+import static org.springframework.http.RequestEntity.options;
+import static org.springframework.http.RequestEntity.post;
/**
+ * Base class for integration tests with {@code @RequestMapping methods}.
*
* @author Rossen Stoyanchev
*/
public abstract class AbstractRequestMappingIntegrationTests extends AbstractHttpHandlerIntegrationTests {
- private ApplicationContext applicationContext;
-
private RestTemplate restTemplate = new RestTemplate();
+ private ApplicationContext applicationContext;
+
@Override
protected HttpHandler createHttpHandler() {
+ this.restTemplate = initRestTemplate();
this.applicationContext = initApplicationContext();
return WebHttpHandlerBuilder
.webHandler(new DispatcherHandler(this.applicationContext))
@@ -53,49 +61,98 @@ public abstract class AbstractRequestMappingIntegrationTests extends AbstractHtt
protected abstract ApplicationContext initApplicationContext();
+ protected RestTemplate initRestTemplate() {
+ return new RestTemplate();
+ }
- ApplicationContext getApplicationContext() {
+ protected ApplicationContext getApplicationContext() {
return this.applicationContext;
}
- RestTemplate getRestTemplate() {
+ protected RestTemplate getRestTemplate() {
return this.restTemplate;
}
- ResponseEntity performGet(String url, MediaType out,
- Class type) throws Exception {
-
- return this.restTemplate.exchange(prepareGet(url, out), type);
+ ResponseEntity performGet(String url, MediaType out, Class type) throws Exception {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setAccept(Collections.singletonList(out));
+ return getRestTemplate().exchange(prepareGet(url, headers), type);
}
- ResponseEntity performGet(String url, MediaType out,
- ParameterizedTypeReference type) throws Exception {
+ ResponseEntity performGet(String url, HttpHeaders headers, Class type) throws Exception {
+ return getRestTemplate().exchange(prepareGet(url, headers), type);
+ }
- return this.restTemplate.exchange(prepareGet(url, out), type);
+ ResponseEntity performGet(String url, MediaType out, ParameterizedTypeReference type)
+ throws Exception {
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setAccept(Collections.singletonList(out));
+ return this.restTemplate.exchange(prepareGet(url, headers), type);
+ }
+
+ ResponseEntity performOptions(String url, HttpHeaders headers, Class type)
+ throws Exception {
+
+ return getRestTemplate().exchange(prepareOptions(url, headers), type);
+ }
+
+ ResponseEntity performPost(String url, MediaType in, Object body, MediaType out, Class type)
+ throws Exception {
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(in);
+ if (out != null) {
+ headers.setAccept(Collections.singletonList(out));
+ }
+ return getRestTemplate().exchange(preparePost(url, headers, body), type);
+ }
+
+ ResponseEntity performPost(String url, HttpHeaders headers, Object body,
+ Class type) throws Exception {
+
+ return getRestTemplate().exchange(preparePost(url, headers, body), type);
}
ResponseEntity performPost(String url, MediaType in, Object body, MediaType out,
- Class type) throws Exception {
+ ParameterizedTypeReference type) throws Exception {
- return this.restTemplate.exchange(preparePost(url, in, body, out), type);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(in);
+ if (out != null) {
+ headers.setAccept(Collections.singletonList(out));
+ }
+ return getRestTemplate().exchange(preparePost(url, headers, body), type);
}
- ResponseEntity performPost(String url, MediaType in, Object body,
- MediaType out, ParameterizedTypeReference type) throws Exception {
-
- return this.restTemplate.exchange(preparePost(url, in, body, out), type);
- }
-
- private RequestEntity prepareGet(String url, MediaType accept) throws Exception {
+ private RequestEntity prepareGet(String url, HttpHeaders headers) throws Exception {
URI uri = new URI("http://localhost:" + this.port + url);
- return (accept != null ? get(uri).accept(accept).build() : get(uri).build());
+ RequestEntity.HeadersBuilder> builder = get(uri);
+ addHeaders(builder, headers);
+ return builder.build();
}
- private RequestEntity> preparePost(String url, MediaType in, Object body, MediaType out) throws Exception {
+ private RequestEntity prepareOptions(String url, HttpHeaders headers) throws Exception {
URI uri = new URI("http://localhost:" + this.port + url);
- return (out != null ?
- RequestEntity.post(uri).contentType(in).accept(out).body(body) :
- RequestEntity.post(uri).contentType(in).body(body));
+ RequestEntity.HeadersBuilder> builder = options(uri);
+ addHeaders(builder, headers);
+ return builder.build();
}
+
+ private void addHeaders(RequestEntity.HeadersBuilder> builder, HttpHeaders headers) {
+ for (Map.Entry> entry : headers.entrySet()) {
+ for (String value : entry.getValue()) {
+ builder.header(entry.getKey(), value);
+ }
+ }
+ }
+
+ private RequestEntity> preparePost(String url, HttpHeaders headers, Object body) throws Exception {
+ URI uri = new URI("http://localhost:" + this.port + url);
+ RequestEntity.BodyBuilder builder = post(uri);
+ addHeaders(builder, headers);
+ return builder.body(body);
+ }
+
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CrossOriginAnnotationIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CrossOriginAnnotationIntegrationTests.java
index 1e5a9fdc0f..fcf44e7c5f 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CrossOriginAnnotationIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CrossOriginAnnotationIntegrationTests.java
@@ -18,8 +18,7 @@ package org.springframework.web.reactive.result.method.annotation;
import java.util.Properties;
-import static org.junit.Assert.*;
-import static org.junit.Assert.assertArrayEquals;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
@@ -28,76 +27,82 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.PropertiesPropertySource;
-import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.config.WebReactiveConfiguration;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
/**
+ * Integration tests with {@code @CrossOrigin} and {@code @RequestMapping}
+ * annotated handler methods.
+ *
* @author Sebastien Deleuze
+ * @author Rossen Stoyanchev
*/
public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappingIntegrationTests {
- // JDK default HTTP client blacklist headers like Origin
- private RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
+ private HttpHeaders headers;
+
+
+ @Before
+ public void setup() throws Exception {
+ super.setup();
+ this.headers = new HttpHeaders();
+ this.headers.setOrigin("http://site1.com");
+ }
@Override
protected ApplicationContext initApplicationContext() {
- AnnotationConfigApplicationContext wac = new AnnotationConfigApplicationContext();
- wac.register(WebConfig.class);
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ context.register(WebConfig.class);
Properties props = new Properties();
props.setProperty("myOrigin", "http://site1.com");
- wac.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("ps", props));
- wac.register(PropertySourcesPlaceholderConfigurer.class);
- wac.refresh();
- return wac;
+ context.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("ps", props));
+ context.register(PropertySourcesPlaceholderConfigurer.class);
+ context.refresh();
+ return context;
}
@Override
- RestTemplate getRestTemplate() {
- return this.restTemplate;
+ protected RestTemplate initRestTemplate() {
+ // JDK default HTTP client blacklist headers like Origin
+ return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
+
@Test
- public void actualGetRequestWithoutAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/no"),
- HttpMethod.GET, requestEntity, String.class);
+ public void actualGetRequestWithoutAnnotation() throws Exception {
+ ResponseEntity entity = performGet("/no", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertNull(entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("no", entity.getBody());
}
@Test
- public void actualPostRequestWithoutAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/no"),
- HttpMethod.POST, requestEntity, String.class);
+ public void actualPostRequestWithoutAnnotation() throws Exception {
+ ResponseEntity entity = performPost("/no", this.headers, null, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertNull(entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("no-post", entity.getBody());
}
@Test
- public void actualRequestWithDefaultAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/default"),
- HttpMethod.GET, requestEntity, String.class);
+ public void actualRequestWithDefaultAnnotation() throws Exception {
+ ResponseEntity entity = performGet("/default", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
@@ -105,13 +110,9 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
}
@Test
- public void preflightRequestWithDefaultAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/default"),
- HttpMethod.OPTIONS, requestEntity, Void.class);
+ public void preflightRequestWithDefaultAnnotation() throws Exception {
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ ResponseEntity entity = performOptions("/default", this.headers, Void.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(1800, entity.getHeaders().getAccessControlMaxAge());
@@ -119,23 +120,17 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
}
@Test
- public void actualRequestWithDefaultAnnotationAndNoOrigin() {
+ public void actualRequestWithDefaultAnnotationAndNoOrigin() throws Exception {
HttpHeaders headers = new HttpHeaders();
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/default"),
- HttpMethod.GET, requestEntity, String.class);
+ ResponseEntity entity = performGet("/default", headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertNull(entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("default", entity.getBody());
}
@Test
- public void actualRequestWithCustomizedAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/customized"),
- HttpMethod.GET, requestEntity, String.class);
+ public void actualRequestWithCustomizedAnnotation() throws Exception {
+ ResponseEntity entity = performGet("/customized", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
@@ -144,67 +139,54 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
}
@Test
- public void preflightRequestWithCustomizedAnnotation() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "header1, header2");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/customized"),
- HttpMethod.OPTIONS, requestEntity, String.class);
+ public void preflightRequestWithCustomizedAnnotation() throws Exception {
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "header1, header2");
+ ResponseEntity entity = performOptions("/customized", this.headers, String.class);
+
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
- assertArrayEquals(new HttpMethod[] {HttpMethod.GET}, entity.getHeaders().getAccessControlAllowMethods().toArray());
+ assertArrayEquals(new HttpMethod[] {HttpMethod.GET},
+ entity.getHeaders().getAccessControlAllowMethods().toArray());
+ assertArrayEquals(new String[] {"header1", "header2"},
+ entity.getHeaders().getAccessControlAllowHeaders().toArray());
+ assertArrayEquals(new String[] {"header3", "header4"},
+ entity.getHeaders().getAccessControlExposeHeaders().toArray());
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
- assertArrayEquals(new String[] {"header1", "header2"}, entity.getHeaders().getAccessControlAllowHeaders().toArray());
- assertArrayEquals(new String[] {"header3", "header4"}, entity.getHeaders().getAccessControlExposeHeaders().toArray());
assertEquals(123, entity.getHeaders().getAccessControlMaxAge());
}
@Test
- public void customOriginDefinedViaValueAttribute() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/origin-value-attribute"),
- HttpMethod.GET, requestEntity, String.class);
+ public void customOriginDefinedViaValueAttribute() throws Exception {
+ ResponseEntity entity = performGet("/origin-value-attribute", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("value-attribute", entity.getBody());
}
@Test
- public void customOriginDefinedViaPlaceholder() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/origin-placeholder"),
- HttpMethod.GET, requestEntity, String.class);
+ public void customOriginDefinedViaPlaceholder() throws Exception {
+ ResponseEntity entity = performGet("/origin-placeholder", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("placeholder", entity.getBody());
}
@Test
- public void classLevel() {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- HttpEntity> requestEntity = new HttpEntity(headers);
-
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/foo"),
- HttpMethod.GET, requestEntity, String.class);
+ public void classLevel() throws Exception {
+ ResponseEntity entity = performGet("/foo", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
assertEquals("foo", entity.getBody());
- entity = this.restTemplate.exchange(getUrl("/bar"), HttpMethod.GET, requestEntity, String.class);
+ entity = performGet("/bar", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("*", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(false, entity.getHeaders().getAccessControlAllowCredentials());
assertEquals("bar", entity.getBody());
- entity = this.restTemplate.exchange(getUrl("/baz"), HttpMethod.GET, requestEntity, String.class);
+ entity = performGet("/baz", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
@@ -213,107 +195,104 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
@Test
public void ambiguousHeaderPreflightRequest() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "header1");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/ambiguous-header"),
- HttpMethod.OPTIONS, requestEntity, String.class);
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "header1");
+ ResponseEntity entity = performOptions("/ambiguous-header", this.headers, String.class);
+
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
- assertArrayEquals(new HttpMethod[] {HttpMethod.GET}, entity.getHeaders().getAccessControlAllowMethods().toArray());
+ assertArrayEquals(new HttpMethod[] {HttpMethod.GET},
+ entity.getHeaders().getAccessControlAllowMethods().toArray());
+ assertArrayEquals(new String[] {"header1"},
+ entity.getHeaders().getAccessControlAllowHeaders().toArray());
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
- assertArrayEquals(new String[] {"header1"}, entity.getHeaders().getAccessControlAllowHeaders().toArray());
}
@Test
public void ambiguousProducesPreflightRequest() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://site1.com");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/ambiguous-produces"),
- HttpMethod.OPTIONS, requestEntity, String.class);
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ ResponseEntity entity = performOptions("/ambiguous-produces", this.headers, String.class);
+
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://site1.com", entity.getHeaders().getAccessControlAllowOrigin());
- assertArrayEquals(new HttpMethod[] {HttpMethod.GET}, entity.getHeaders().getAccessControlAllowMethods().toArray());
+ assertArrayEquals(new HttpMethod[] {HttpMethod.GET},
+ entity.getHeaders().getAccessControlAllowMethods().toArray());
assertEquals(true, entity.getHeaders().getAccessControlAllowCredentials());
}
- private String getUrl(String path) {
- return "http://localhost:" + this.port + path;
- }
-
@Configuration
@ComponentScan(resourcePattern = "**/CrossOriginAnnotationIntegrationTests*")
@SuppressWarnings({"unused", "WeakerAccess"})
static class WebConfig extends WebReactiveConfiguration {
-
}
- @RestController
+ @RestController @SuppressWarnings("unused")
private static class MethodLevelController {
- @RequestMapping(path = "/no", method = RequestMethod.GET)
+ @GetMapping("/no")
public String noAnnotation() {
return "no";
}
- @RequestMapping(path = "/no", method = RequestMethod.POST)
+ @PostMapping("/no")
public String noAnnotationPost() {
return "no-post";
}
@CrossOrigin
- @RequestMapping(path = "/default", method = RequestMethod.GET)
+ @GetMapping("/default")
public String defaultAnnotation() {
return "default";
}
@CrossOrigin
- @RequestMapping(path = "/default", method = RequestMethod.GET, params = "q")
+ @GetMapping(path = "/default", params = "q")
public void defaultAnnotationWithParams() {
}
@CrossOrigin
- @RequestMapping(path = "/ambiguous-header", method = RequestMethod.GET, headers = "header1=a")
+ @GetMapping(path = "/ambiguous-header", headers = "header1=a")
public void ambigousHeader1a() {
}
@CrossOrigin
- @RequestMapping(path = "/ambiguous-header", method = RequestMethod.GET, headers = "header1=b")
+ @GetMapping(path = "/ambiguous-header", headers = "header1=b")
public void ambigousHeader1b() {
}
@CrossOrigin
- @RequestMapping(path = "/ambiguous-produces", method = RequestMethod.GET, produces = "application/xml")
+ @GetMapping(path = "/ambiguous-produces", produces = "application/xml")
public String ambigousProducesXml() {
return " ";
}
@CrossOrigin
- @RequestMapping(path = "/ambiguous-produces", method = RequestMethod.GET, produces = "application/json")
+ @GetMapping(path = "/ambiguous-produces", produces = "application/json")
public String ambigousProducesJson() {
return "{}";
}
- @CrossOrigin(origins = { "http://site1.com", "http://site2.com" }, allowedHeaders = { "header1", "header2" },
- exposedHeaders = { "header3", "header4" }, methods = RequestMethod.GET, maxAge = 123, allowCredentials = "false")
+ @CrossOrigin(
+ origins = { "http://site1.com", "http://site2.com" },
+ allowedHeaders = { "header1", "header2" },
+ exposedHeaders = { "header3", "header4" },
+ methods = RequestMethod.GET,
+ maxAge = 123,
+ allowCredentials = "false")
@RequestMapping(path = "/customized", method = { RequestMethod.GET, RequestMethod.POST })
public String customized() {
return "customized";
}
@CrossOrigin("http://site1.com")
- @RequestMapping("/origin-value-attribute")
+ @GetMapping("/origin-value-attribute")
public String customOriginDefinedViaValueAttribute() {
return "value-attribute";
}
@CrossOrigin("${myOrigin}")
- @RequestMapping("/origin-placeholder")
+ @GetMapping("/origin-placeholder")
public String customOriginDefinedViaPlaceholder() {
return "placeholder";
}
@@ -321,25 +300,25 @@ public class CrossOriginAnnotationIntegrationTests extends AbstractRequestMappin
@RestController
@CrossOrigin(allowCredentials = "false")
+ @SuppressWarnings("unused")
private static class ClassLevelController {
- @RequestMapping(path = "/foo", method = RequestMethod.GET)
+ @GetMapping("/foo")
public String foo() {
return "foo";
}
@CrossOrigin
- @RequestMapping(path = "/bar", method = RequestMethod.GET)
+ @GetMapping("/bar")
public String bar() {
return "bar";
}
@CrossOrigin(allowCredentials = "true")
- @RequestMapping(path = "/baz", method = RequestMethod.GET)
+ @GetMapping("/baz")
public String baz() {
return "baz";
}
-
}
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CorsConfigurationIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/GlobalCorsConfigIntegrationTests.java
similarity index 54%
rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CorsConfigurationIntegrationTests.java
rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/GlobalCorsConfigIntegrationTests.java
index b461559e2a..ce4dc61b6a 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/CorsConfigurationIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/GlobalCorsConfigIntegrationTests.java
@@ -16,16 +16,14 @@
package org.springframework.web.reactive.result.method.annotation;
-import static org.junit.Assert.*;
+import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@@ -36,34 +34,49 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.WebReactiveConfiguration;
-/**
- * @author Sebastien Deleuze
- */
-public class CorsConfigurationIntegrationTests extends AbstractRequestMappingIntegrationTests {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+/**
+ *
+ * Integration tests with {@code @RequestMapping} handler methods and global
+ * CORS configuration.
+ *
+ * @author Sebastien Deleuze
+ * @author Rossen Stoyanchev
+ */
+public class GlobalCorsConfigIntegrationTests extends AbstractRequestMappingIntegrationTests {
+
+ private HttpHeaders headers;
+
+
+ @Before
+ public void setup() throws Exception {
+ super.setup();
+ this.headers = new HttpHeaders();
+ this.headers.setOrigin("http://localhost:9000");
+ }
- // JDK default HTTP client blacklist headers like Origin
- private RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
@Override
protected ApplicationContext initApplicationContext() {
- AnnotationConfigApplicationContext wac = new AnnotationConfigApplicationContext();
- wac.register(WebConfig.class);
- wac.refresh();
- return wac;
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ context.register(WebConfig.class);
+ context.refresh();
+ return context;
}
@Override
- RestTemplate getRestTemplate() {
- return this.restTemplate;
+ protected RestTemplate initRestTemplate() {
+ // JDK default HTTP client blacklists headers like Origin
+ return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
}
+
@Test
public void actualRequestWithCorsEnabled() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/cors"),
- HttpMethod.GET, requestEntity, String.class);
+ ResponseEntity entity = performGet("/cors", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://localhost:9000", entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("cors", entity.getBody());
@@ -71,85 +84,58 @@ public class CorsConfigurationIntegrationTests extends AbstractRequestMappingInt
@Test
public void actualRequestWithCorsRejected() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- HttpEntity> requestEntity = new HttpEntity(headers);
try {
- this.restTemplate.exchange(getUrl("/cors-restricted"), HttpMethod.GET,
- requestEntity, String.class);
+ performGet("/cors-restricted", this.headers, String.class);
+ fail();
}
catch (HttpClientErrorException e) {
assertEquals(HttpStatus.FORBIDDEN, e.getStatusCode());
- return;
}
- fail();
}
@Test
public void actualRequestWithoutCorsEnabled() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/welcome"),
- HttpMethod.GET, requestEntity, String.class);
+ ResponseEntity entity = performGet("/welcome", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertNull(entity.getHeaders().getAccessControlAllowOrigin());
assertEquals("welcome", entity.getBody());
}
@Test
- public void preflightRequestWithCorsEnabled() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- HttpEntity> requestEntity = new HttpEntity(headers);
- ResponseEntity entity = this.restTemplate.exchange(getUrl("/cors"),
- HttpMethod.OPTIONS, requestEntity, String.class);
+ public void preFlightRequestWithCorsEnabled() throws Exception {
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ ResponseEntity entity = performOptions("/cors", this.headers, String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("http://localhost:9000", entity.getHeaders().getAccessControlAllowOrigin());
}
@Test
- public void preflightRequestWithCorsRejected() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- HttpEntity> requestEntity = new HttpEntity(headers);
+ public void preFlightRequestWithCorsRejected() throws Exception {
try {
- this.restTemplate.exchange(getUrl("/cors-restricted"), HttpMethod.OPTIONS,
- requestEntity, String.class);
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ performOptions("/cors-restricted", this.headers, String.class);
+ fail();
}
catch (HttpClientErrorException e) {
assertEquals(HttpStatus.FORBIDDEN, e.getStatusCode());
- return;
}
- fail();
}
@Test
- public void preflightRequestWithoutCorsEnabled() throws Exception {
- HttpHeaders headers = new HttpHeaders();
- headers.add(HttpHeaders.ORIGIN, "http://localhost:9000");
- headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- HttpEntity> requestEntity = new HttpEntity(headers);
+ public void preFlightRequestWithoutCorsEnabled() throws Exception {
try {
- this.restTemplate.exchange(getUrl("/welcome"), HttpMethod.OPTIONS,
- requestEntity, String.class);
+ this.headers.add(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ performOptions("/welcome", this.headers, String.class);
+ fail();
}
catch (HttpClientErrorException e) {
assertEquals(HttpStatus.FORBIDDEN, e.getStatusCode());
- return;
}
- fail();
- }
-
- private String getUrl(String path) {
- return "http://localhost:" + this.port + path;
}
@Configuration
- @ComponentScan(resourcePattern = "**/CorsConfigurationIntegrationTests*.class")
+ @ComponentScan(resourcePattern = "**/GlobalCorsConfigIntegrationTests*.class")
@SuppressWarnings({"unused", "WeakerAccess"})
static class WebConfig extends WebReactiveConfiguration {
@@ -160,7 +146,7 @@ public class CorsConfigurationIntegrationTests extends AbstractRequestMappingInt
}
}
- @RestController
+ @RestController @SuppressWarnings("unused")
static class TestController {
@GetMapping("/welcome")
@@ -177,7 +163,6 @@ public class CorsConfigurationIntegrationTests extends AbstractRequestMappingInt
public String corsRestricted() {
return "corsRestricted";
}
-
}
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java
index c11d2d6ded..04758fd8cc 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingExceptionHandlingIntegrationTests.java
@@ -24,6 +24,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -52,13 +53,13 @@ public class RequestMappingExceptionHandlingIntegrationTests extends AbstractReq
@Test
public void controllerThrowingException() throws Exception {
String expected = "Recovered from error: Boo";
- assertEquals(expected, performGet("/thrown-exception", null, String.class).getBody());
+ assertEquals(expected, performGet("/thrown-exception", new HttpHeaders(), String.class).getBody());
}
@Test
public void controllerReturnsMonoError() throws Exception {
String expected = "Recovered from error: Boo";
- assertEquals(expected, performGet("/mono-error", null, String.class).getBody());
+ assertEquals(expected, performGet("/mono-error", new HttpHeaders(), String.class).getBody());
}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java
index 65d6ac4fb3..733a0da8df 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingIntegrationTests.java
@@ -24,6 +24,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -56,13 +57,13 @@ public class RequestMappingIntegrationTests extends AbstractRequestMappingIntegr
@Test
public void handleWithParam() throws Exception {
String expected = "Hello George!";
- assertEquals(expected, performGet("/param?name=George", null, String.class).getBody());
+ assertEquals(expected, performGet("/param?name=George", new HttpHeaders(), String.class).getBody());
}
@Test
public void longStreamResult() throws Exception {
String[] expected = {"0", "1", "2", "3", "4"};
- assertArrayEquals(expected, performGet("/long-stream-result", null, String[].class).getBody());
+ assertArrayEquals(expected, performGet("/long-stream-result", new HttpHeaders(), String[].class).getBody());
}
@Test
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java
index 73b00b00fd..589f29fbb9 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingMessageConversionIntegrationTests.java
@@ -45,6 +45,7 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -94,25 +95,26 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
@Test
public void byteBufferResponseBodyWithFlux() throws Exception {
String expected = "Hello!";
- assertEquals(expected, performGet("/raw-response/flux", null, String.class).getBody());
+ assertEquals(expected, performGet("/raw-response/flux", new HttpHeaders(), String.class).getBody());
}
@Test
public void byteBufferResponseBodyWithObservable() throws Exception {
String expected = "Hello!";
- assertEquals(expected, performGet("/raw-response/observable", null, String.class).getBody());
+ assertEquals(expected, performGet("/raw-response/observable", new HttpHeaders(), String.class).getBody());
}
@Test
public void byteBufferResponseBodyWithRxJava2Observable() throws Exception {
String expected = "Hello!";
- assertEquals(expected, performGet("/raw-response/rxjava2-observable", null, String.class).getBody());
+ assertEquals(expected, performGet("/raw-response/rxjava2-observable",
+ new HttpHeaders(), String.class).getBody());
}
@Test
public void byteBufferResponseBodyWithFlowable() throws Exception {
String expected = "Hello!";
- assertEquals(expected, performGet("/raw-response/flowable", null, String.class).getBody());
+ assertEquals(expected, performGet("/raw-response/flowable", new HttpHeaders(), String.class).getBody());
}
@Test
@@ -171,7 +173,7 @@ public class RequestMappingMessageConversionIntegrationTests extends AbstractReq
@Test
public void resource() throws Exception {
- ResponseEntity response = performGet("/resource", null, byte[].class);
+ ResponseEntity response = performGet("/resource", new HttpHeaders(), byte[].class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response.hasBody());
diff --git a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java
index f2b7c57858..adfebe204a 100644
--- a/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java
+++ b/spring-web/src/main/java/org/springframework/web/cors/reactive/DefaultCorsProcessor.java
@@ -63,12 +63,12 @@ public class DefaultCorsProcessor implements CorsProcessor {
}
if (responseHasCors(response)) {
- logger.debug("Skip CORS processing: response already contains \"Access-Control-Allow-Origin\" header");
+ logger.debug("Skip CORS: response already contains \"Access-Control-Allow-Origin\" header");
return true;
}
if (CorsUtils.isSameOrigin(request)) {
- logger.debug("Skip CORS processing: request is from same origin");
+ logger.debug("Skip CORS: request is from same origin");
return true;
}
diff --git a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java
index a2cb70958d..46cbaad09c 100644
--- a/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java
+++ b/spring-web/src/test/java/org/springframework/web/cors/reactive/DefaultCorsProcessorTests.java
@@ -16,7 +16,6 @@
package org.springframework.web.cors.reactive;
-import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
@@ -26,17 +25,22 @@ import org.springframework.http.HttpStatus;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.reactive.DefaultCorsProcessor;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS;
+import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
+import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS;
+import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD;
+
/**
- * Test reactive {@link DefaultCorsProcessor} with simple or preflight CORS request.
+ * {@link DefaultCorsProcessor} tests with simple or pre-flight CORS request.
*
* @author Sebastien Deleuze
- * @author Rossen Stoyanchev
- * @author Juergen Hoeller
*/
public class DefaultCorsProcessorTests {
@@ -69,7 +73,7 @@ public class DefaultCorsProcessorTests {
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
}
@@ -79,7 +83,7 @@ public class DefaultCorsProcessorTests {
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
this.processor.processRequest(null, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -90,8 +94,8 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedOrigin("*");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("*", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("*", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE));
assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
@@ -107,8 +111,8 @@ public class DefaultCorsProcessorTests {
this.conf.setAllowCredentials(true);
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("http://domain2.com", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals("true", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
@@ -122,8 +126,8 @@ public class DefaultCorsProcessorTests {
this.conf.setAllowCredentials(true);
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("http://domain2.com", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals("true", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
@@ -136,7 +140,7 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedOrigin("http://DOMAIN2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -149,8 +153,8 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedOrigin("http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("http://domain2.com", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS));
assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header1"));
assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS).contains("header2"));
@@ -161,7 +165,7 @@ public class DefaultCorsProcessorTests {
public void preflightRequestAllOriginsAllowed() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
this.conf.addAllowedOrigin("*");
this.processor.processRequest(this.conf, this.exchange);
@@ -172,7 +176,7 @@ public class DefaultCorsProcessorTests {
public void preflightRequestWrongAllowedMethod() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "DELETE");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "DELETE");
this.conf.addAllowedOrigin("*");
this.processor.processRequest(this.conf, this.exchange);
@@ -183,7 +187,7 @@ public class DefaultCorsProcessorTests {
public void preflightRequestMatchedAllowedMethod() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
this.conf.addAllowedOrigin("*");
this.processor.processRequest(this.conf, this.exchange);
@@ -197,7 +201,7 @@ public class DefaultCorsProcessorTests {
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
}
@@ -205,10 +209,10 @@ public class DefaultCorsProcessorTests {
public void preflightRequestWithoutRequestMethod() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
this.processor.processRequest(this.conf, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
}
@@ -216,11 +220,11 @@ public class DefaultCorsProcessorTests {
public void preflightRequestWithRequestAndMethodHeaderButNoConfig() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
this.processor.processRequest(this.conf, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
}
@@ -228,8 +232,8 @@ public class DefaultCorsProcessorTests {
public void preflightRequestValidRequestAndConfig() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
this.conf.addAllowedOrigin("*");
this.conf.addAllowedMethod("GET");
this.conf.addAllowedMethod("PUT");
@@ -237,8 +241,8 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedHeader("header2");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("*", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("*", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
assertEquals("GET,PUT", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE));
@@ -249,8 +253,8 @@ public class DefaultCorsProcessorTests {
public void preflightRequestCredentials() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
this.conf.addAllowedOrigin("http://domain1.com");
this.conf.addAllowedOrigin("http://domain2.com");
this.conf.addAllowedOrigin("http://domain3.com");
@@ -258,8 +262,8 @@ public class DefaultCorsProcessorTests {
this.conf.setAllowCredentials(true);
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("http://domain2.com", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals("true", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
@@ -269,8 +273,8 @@ public class DefaultCorsProcessorTests {
public void preflightRequestCredentialsWithOriginWildcard() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
this.conf.addAllowedOrigin("http://domain1.com");
this.conf.addAllowedOrigin("*");
this.conf.addAllowedOrigin("http://domain3.com");
@@ -278,8 +282,8 @@ public class DefaultCorsProcessorTests {
this.conf.setAllowCredentials(true);
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertEquals("http://domain2.com", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -287,19 +291,19 @@ public class DefaultCorsProcessorTests {
public void preflightRequestAllowedHeaders() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
this.conf.addAllowedHeader("Header1");
this.conf.addAllowedHeader("Header2");
this.conf.addAllowedHeader("Header3");
this.conf.addAllowedOrigin("http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS));
- assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
- assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
- assertFalse(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3"));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
+ assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
+ assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
+ assertFalse(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header3"));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -307,17 +311,17 @@ public class DefaultCorsProcessorTests {
public void preflightRequestAllowsAllHeaders() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
this.conf.addAllowedHeader("*");
this.conf.addAllowedOrigin("http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS));
- assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
- assertTrue(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
- assertFalse(this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS).contains("*"));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
+ assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
+ assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header2"));
+ assertFalse(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("*"));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -325,14 +329,14 @@ public class DefaultCorsProcessorTests {
public void preflightRequestWithEmptyHeaders() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "");
this.conf.addAllowedHeader("*");
this.conf.addAllowedOrigin("http://domain2.com");
this.processor.processRequest(this.conf, this.exchange);
- assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS));
+ assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
assertEquals(HttpStatus.OK, this.response.getStatusCode());
}
@@ -340,11 +344,11 @@ public class DefaultCorsProcessorTests {
public void preflightRequestWithNullConfig() throws Exception {
this.request.setHttpMethod(HttpMethod.OPTIONS);
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
- this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
+ this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
this.conf.addAllowedOrigin("*");
this.processor.processRequest(null, this.exchange);
- assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
+ assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
}
diff --git a/spring-web/src/test/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSourceTests.java b/spring-web/src/test/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSourceTests.java
index f0be0bfade..9ad06c2b8c 100644
--- a/spring-web/src/test/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSourceTests.java
+++ b/spring-web/src/test/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSourceTests.java
@@ -16,8 +16,6 @@
package org.springframework.web.cors.reactive;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.springframework.http.HttpMethod;
@@ -29,19 +27,23 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.adapter.DefaultServerWebExchange;
import org.springframework.web.server.session.MockWebSessionManager;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
/**
- * Unit tests for reactive {@link UrlBasedCorsConfigurationSource}.
+ * Unit tests for {@link UrlBasedCorsConfigurationSource}.
+ *
* @author Sebastien Deleuze
+ * @author Rossen Stoyanchev
*/
public class UrlBasedCorsConfigurationSourceTests {
private final UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
+
@Test
public void empty() {
- ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/bar/test.html");
- ServerWebExchange exchange = new DefaultServerWebExchange(request,
- new MockServerHttpResponse(), new MockWebSessionManager());
+ ServerWebExchange exchange = createExchange(HttpMethod.GET, "/bar/test.html");
assertNull(this.configSource.getCorsConfiguration(exchange));
}
@@ -49,15 +51,12 @@ public class UrlBasedCorsConfigurationSourceTests {
public void registerAndMatch() {
CorsConfiguration config = new CorsConfiguration();
this.configSource.registerCorsConfiguration("/bar/**", config);
- assertNull(this.configSource.getCorsConfiguration(
- new DefaultServerWebExchange(
- new MockServerHttpRequest(HttpMethod.GET, "/foo/test.html"),
- new MockServerHttpResponse(),
- new MockWebSessionManager())));
- assertEquals(config, this.configSource.getCorsConfiguration(new DefaultServerWebExchange(
- new MockServerHttpRequest(HttpMethod.GET, "/bar/test.html"),
- new MockServerHttpResponse(),
- new MockWebSessionManager())));
+
+ ServerWebExchange exchange = createExchange(HttpMethod.GET, "/foo/test.html");
+ assertNull(this.configSource.getCorsConfiguration(exchange));
+
+ exchange = createExchange(HttpMethod.GET, "/bar/test.html");
+ assertEquals(config, this.configSource.getCorsConfiguration(exchange));
}
@Test(expected = UnsupportedOperationException.class)
@@ -65,4 +64,12 @@ public class UrlBasedCorsConfigurationSourceTests {
this.configSource.getCorsConfigurations().put("/**", new CorsConfiguration());
}
+
+ private ServerWebExchange createExchange(HttpMethod httpMethod, String url) {
+ ServerHttpRequest request = new MockServerHttpRequest(httpMethod, url);
+ MockServerHttpResponse response = new MockServerHttpResponse();
+ MockWebSessionManager sessionManager = new MockWebSessionManager();
+ return new DefaultServerWebExchange(request, response, sessionManager);
+ }
+
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java
index 41a3ae56bc..568dd9bfdf 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/CorsRegistration.java
@@ -46,6 +46,7 @@ public class CorsRegistration {
private final CorsConfiguration config;
+
public CorsRegistration(String pathPattern) {
this.pathPattern = pathPattern;
// Same implicit default values as the @CrossOrigin annotation + allows simple methods
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java
index 39c7a24407..a44ee50143 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java
@@ -78,9 +78,9 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
private final List adaptedInterceptors = new ArrayList<>();
- private CorsProcessor corsProcessor = new DefaultCorsProcessor();
+ private final UrlBasedCorsConfigurationSource globalCorsConfigSource = new UrlBasedCorsConfigurationSource();
- private final UrlBasedCorsConfigurationSource corsConfigSource = new UrlBasedCorsConfigurationSource();
+ private CorsProcessor corsProcessor = new DefaultCorsProcessor();
/**
@@ -123,7 +123,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
*/
public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
- this.corsConfigSource.setAlwaysUseFullPath(alwaysUseFullPath);
+ this.globalCorsConfigSource.setAlwaysUseFullPath(alwaysUseFullPath);
}
/**
@@ -135,7 +135,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
*/
public void setUrlDecode(boolean urlDecode) {
this.urlPathHelper.setUrlDecode(urlDecode);
- this.corsConfigSource.setUrlDecode(urlDecode);
+ this.globalCorsConfigSource.setUrlDecode(urlDecode);
}
/**
@@ -145,7 +145,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
*/
public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
- this.corsConfigSource.setRemoveSemicolonContent(removeSemicolonContent);
+ this.globalCorsConfigSource.setRemoveSemicolonContent(removeSemicolonContent);
}
/**
@@ -157,7 +157,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
this.urlPathHelper = urlPathHelper;
- this.corsConfigSource.setUrlPathHelper(urlPathHelper);
+ this.globalCorsConfigSource.setUrlPathHelper(urlPathHelper);
}
/**
@@ -175,7 +175,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
public void setPathMatcher(PathMatcher pathMatcher) {
Assert.notNull(pathMatcher, "PathMatcher must not be null");
this.pathMatcher = pathMatcher;
- this.corsConfigSource.setPathMatcher(pathMatcher);
+ this.globalCorsConfigSource.setPathMatcher(pathMatcher);
}
/**
@@ -200,6 +200,23 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
this.interceptors.addAll(Arrays.asList(interceptors));
}
+ /**
+ * Set "global" CORS configuration based on URL patterns. By default the first
+ * matching URL pattern is combined with the CORS configuration for the
+ * handler, if any.
+ * @since 4.2
+ */
+ public void setCorsConfigurations(Map corsConfigurations) {
+ this.globalCorsConfigSource.setCorsConfigurations(corsConfigurations);
+ }
+
+ /**
+ * Get the "global" CORS configuration.
+ */
+ public Map getCorsConfigurations() {
+ return this.globalCorsConfigSource.getCorsConfigurations();
+ }
+
/**
* Configure a custom {@link CorsProcessor} to use to apply the matched
* {@link CorsConfiguration} for a request.
@@ -218,23 +235,6 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
return this.corsProcessor;
}
- /**
- * Set "global" CORS configuration based on URL patterns. By default the first
- * matching URL pattern is combined with the CORS configuration for the
- * handler, if any.
- * @since 4.2
- */
- public void setCorsConfigurations(Map corsConfigurations) {
- this.corsConfigSource.setCorsConfigurations(corsConfigurations);
- }
-
- /**
- * Get the CORS configuration.
- */
- public Map getCorsConfigurations() {
- return this.corsConfigSource.getCorsConfigurations();
- }
-
/**
* Initializes the interceptors.
@@ -364,7 +364,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
- CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
+ CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
index b4abdc1698..ce740375c4 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
@@ -293,7 +293,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
@Override
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
- CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
+ Class> beanType = handlerMethod.getBeanType();
+ CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
if (typeAnnotation == null && methodAnnotation == null) {