Support custom CorsConfigurationSource in AbstractHandlerMapping
This commit allows to specify a custom CorsConfigurationSource in AbstractHandlerMapping (both Servlet and Reactive variants). AbstractHandlerMapping#getCorsConfigurations method is now deprecated. Issue: SPR-17067
This commit is contained in:
@@ -53,7 +53,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
|
||||
|
||||
private final PathPatternParser patternParser;
|
||||
|
||||
private final UrlBasedCorsConfigurationSource globalCorsConfigSource;
|
||||
private CorsConfigurationSource corsConfigurationSource;
|
||||
|
||||
private CorsProcessor corsProcessor = new DefaultCorsProcessor();
|
||||
|
||||
@@ -65,7 +65,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
|
||||
|
||||
public AbstractHandlerMapping() {
|
||||
this.patternParser = new PathPatternParser();
|
||||
this.globalCorsConfigSource = new UrlBasedCorsConfigurationSource(this.patternParser);
|
||||
this.corsConfigurationSource = new UrlBasedCorsConfigurationSource(this.patternParser);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,12 +107,25 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "global" CORS configuration based on URL patterns. By default the
|
||||
* first matching URL pattern is combined with handler-level CORS
|
||||
* configuration if any.
|
||||
* Set the "global" CORS configurations based on URL patterns. By default the
|
||||
* first matching URL pattern is combined with handler-level CORS configuration if any.
|
||||
* @see #setCorsConfigurationSource(CorsConfigurationSource)
|
||||
*/
|
||||
public void setCorsConfigurations(Map<String, CorsConfiguration> corsConfigurations) {
|
||||
this.globalCorsConfigSource.setCorsConfigurations(corsConfigurations);
|
||||
Assert.notNull(corsConfigurations, "corsConfigurations must not be null");
|
||||
this.corsConfigurationSource = new UrlBasedCorsConfigurationSource(this.patternParser);
|
||||
((UrlBasedCorsConfigurationSource) this.corsConfigurationSource).setCorsConfigurations(corsConfigurations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "global" CORS configuration source. By default the first matching URL
|
||||
* pattern is combined with the CORS configuration for the handler, if any.
|
||||
* @since 5.1
|
||||
* @see #setCorsConfigurations(Map)
|
||||
*/
|
||||
public void setCorsConfigurationSource(CorsConfigurationSource corsConfigurationSource) {
|
||||
Assert.notNull(corsConfigurationSource, "corsConfigurationSource must not be null");
|
||||
this.corsConfigurationSource = corsConfigurationSource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +176,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
|
||||
logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
|
||||
}
|
||||
if (CorsUtils.isCorsRequest(exchange.getRequest())) {
|
||||
CorsConfiguration configA = this.globalCorsConfigSource.getCorsConfiguration(exchange);
|
||||
CorsConfiguration configA = this.corsConfigurationSource.getCorsConfiguration(exchange);
|
||||
CorsConfiguration configB = getCorsConfiguration(handler, exchange);
|
||||
CorsConfiguration config = (configA != null ? configA.combine(configB) : configB);
|
||||
if (!getCorsProcessor().process(config, exchange) ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,6 +130,38 @@ public class CorsUrlHandlerMappingTests {
|
||||
assertEquals("*", exchange.getResponse().getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actualRequestWithCorsConfigurationSource() throws Exception {
|
||||
this.handlerMapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
|
||||
String origin = "http://domain2.com";
|
||||
ServerWebExchange exchange = createExchange(HttpMethod.GET, "/welcome.html", origin);
|
||||
Object actual = this.handlerMapping.getHandler(exchange).block();
|
||||
|
||||
assertNotNull(actual);
|
||||
assertSame(this.welcomeController, actual);
|
||||
assertEquals("http://domain2.com", exchange.getResponse().getHeaders()
|
||||
.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("true", exchange.getResponse().getHeaders()
|
||||
.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preFlightRequestWithCorsConfigurationSource() throws Exception {
|
||||
this.handlerMapping.setCorsConfigurationSource(new CustomCorsConfigurationSource());
|
||||
|
||||
String origin = "http://domain2.com";
|
||||
ServerWebExchange exchange = createExchange(HttpMethod.OPTIONS, "/welcome.html", origin);
|
||||
Object actual = this.handlerMapping.getHandler(exchange).block();
|
||||
|
||||
assertNotNull(actual);
|
||||
assertNotSame(this.welcomeController, actual);
|
||||
assertEquals("http://domain2.com", exchange.getResponse().getHeaders()
|
||||
.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("true", exchange.getResponse().getHeaders()
|
||||
.getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
}
|
||||
|
||||
|
||||
private ServerWebExchange createExchange(HttpMethod method, String path, String origin) {
|
||||
|
||||
@@ -150,4 +182,15 @@ public class CorsUrlHandlerMappingTests {
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomCorsConfigurationSource implements CorsConfigurationSource {
|
||||
|
||||
@Override
|
||||
public CorsConfiguration getCorsConfiguration(ServerWebExchange exchange) {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOrigin("*");
|
||||
config.setAllowCredentials(true);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user