* Added changes for BAEL-1922 Enable CORS in Spring Webflux (#4724)

This commit is contained in:
rozagerardo 2018-07-19 14:11:57 -03:00 committed by Grzegorz Piwowarek
parent 4288b6cc90
commit baab69a43a
18 changed files with 735 additions and 0 deletions

View File

@ -0,0 +1,25 @@
package com.baeldung.reactive.cors.annotated;
import java.util.Collections;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
@SpringBootApplication(exclude = { MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class }
)
public class CorsOnAnnotatedElementsApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CorsOnAnnotatedElementsApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8081"));
app.run(args);
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.reactive.cors.annotated.controllers;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@CrossOrigin(value = { "http://allowed-origin.com" }, allowedHeaders = { "Baeldung-Another-Allowed" }, maxAge = 900)
@RestController
@RequestMapping("/cors-on-controller")
public class CorsOnClassController {
@PutMapping("/regular-endpoint")
public Mono<String> corsDisabledEndpoint() {
return Mono.just("Regular endpoint");
}
@CrossOrigin
@PutMapping("/cors-enabled-endpoint")
public Mono<String> corsEnabledEndpoint() {
return Mono.just("CORS enabled endpoint");
}
@CrossOrigin({ "http://another-allowed-origin.com" })
@PutMapping("/cors-enabled-origin-restrictive-endpoint")
public Mono<String> corsEnabledOriginRestrictiveEndpoint() {
return Mono.just("CORS enabled endpoint - Origin Restrictive");
}
@CrossOrigin(allowedHeaders = { "Baeldung-Allowed" })
@PutMapping("/cors-enabled-header-restrictive-endpoint")
public Mono<String> corsEnabledHeaderRestrictiveEndpoint() {
return Mono.just("CORS enabled endpoint - Header Restrictive");
}
@CrossOrigin(exposedHeaders = { "Baeldung-Exposed" })
@PutMapping("/cors-enabled-exposed-header-endpoint")
public Mono<String> corsEnabledExposedHeadersEndpoint() {
return Mono.just("CORS enabled endpoint - Exposed Header");
}
@PutMapping("/cors-enabled-mixed-config-endpoint")
@CrossOrigin(allowedHeaders = { "Baeldung-Allowed", "Baeldung-Other-Allowed" }, exposedHeaders = { "Baeldung-Allowed", "Baeldung-Exposed" }, maxAge = 3600)
public Mono<String> corsEnabledHeaderExposedEndpoint() {
return Mono.just("CORS enabled endpoint - Mixed Config");
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.reactive.cors.annotated.controllers;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/cors-on-methods")
public class CorsOnMethodsController {
@PutMapping("/cors-disabled-endpoint")
public Mono<String> corsDisabledEndpoint() {
return Mono.just("CORS disabled endpoint");
}
@CrossOrigin
@PutMapping("/cors-enabled-endpoint")
public Mono<String> corsEnabledEndpoint() {
return Mono.just("CORS enabled endpoint");
}
@CrossOrigin({ "http://allowed-origin.com" })
@PutMapping("/cors-enabled-origin-restrictive-endpoint")
public Mono<String> corsEnabledOriginRestrictiveEndpoint() {
return Mono.just("CORS enabled endpoint - Origin Restrictive");
}
@CrossOrigin(allowedHeaders = { "Baeldung-Allowed" })
@PutMapping("/cors-enabled-header-restrictive-endpoint")
public Mono<String> corsEnabledHeaderRestrictiveEndpoint() {
return Mono.just("CORS enabled endpoint - Header Restrictive");
}
@CrossOrigin(exposedHeaders = { "Baeldung-Exposed" })
@PutMapping("/cors-enabled-exposed-header-endpoint")
public Mono<String> corsEnabledExposedHeadersEndpoint() {
return Mono.just("CORS enabled endpoint - Exposed Header");
}
@PutMapping("/cors-enabled-mixed-config-endpoint")
@CrossOrigin(allowedHeaders = { "Baeldung-Allowed", "Baeldung-Other-Allowed" }, exposedHeaders = { "Baeldung-Allowed", "Baeldung-Exposed" }, maxAge = 3600)
public Mono<String> corsEnabledHeaderExposedEndpoint() {
return Mono.just("CORS enabled endpoint - Mixed Config");
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.reactive.cors.global;
import java.util.Collections;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
@SpringBootApplication(exclude = { MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class }
)
public class CorsGlobalConfigApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CorsGlobalConfigApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8082"));
app.run(args);
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.reactive.cors.global.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
@Configuration
@EnableWebFlux
public class CorsGlobalConfiguration implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("http://allowed-origin.com")
.allowedMethods("PUT")
.allowedHeaders("Baeldung-Allowed", "Baledung-Another-Allowed")
.exposedHeaders("Baeldung-Allowed", "Baeldung-Exposed")
.maxAge(3600);
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.reactive.cors.global.controllers;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/cors-on-global-config-and-more")
public class FurtherCorsConfigsController {
@DeleteMapping("/further-mixed-config-endpoint")
@CrossOrigin(methods = { RequestMethod.DELETE },
allowedHeaders = { "Baeldung-Other-Allowed" },
exposedHeaders = { "Baeldung-Other-Exposed" }
)
public Mono<String> corsEnabledHeaderExposedEndpoint() {
return Mono.just("CORS Global Configured + Request Configs.");
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.reactive.cors.global.controllers;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/cors-on-global-config")
public class RegularRestController {
@PutMapping("/regular-put-endpoint")
public Mono<String> regularPutEndpoint() {
return Mono.just("Regular PUT endpoint");
}
@DeleteMapping("/regular-delete-endpoint")
public Mono<String> regularDeleteEndpoint() {
return Mono.just("Regular DELETE endpoint");
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.reactive.cors.global.functional.handlers;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
@Component
public class FunctionalHandler {
public Mono<ServerResponse> useHandler(final ServerRequest request) {
final String responseMessage = "CORS GLOBAL CONFIG IS NOT EFFECTIVE ON FUNCTIONAL ENDPOINTS!!!";
return ServerResponse.ok()
.body(Mono.just(responseMessage), String.class);
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.reactive.cors.global.functional.routers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import com.baeldung.reactive.cors.global.functional.handlers.FunctionalHandler;
@Configuration
public class CorsRouterFunctions {
@Bean
public RouterFunction<ServerResponse> responseHeaderRoute(@Autowired FunctionalHandler handler) {
return RouterFunctions.route(RequestPredicates.PUT("/global-config-on-functional/cors-disabled-functional-endpoint"), handler::useHandler);
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.reactive.cors.webfilter;
import java.util.Collections;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
@SpringBootApplication(exclude = { MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class }
)
public class CorsWebFilterApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CorsWebFilterApplication.class);
app.setDefaultProperties(Collections.singletonMap("server.port", "8083"));
app.run(args);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.reactive.cors.webfilter.config;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class CorsWebFilterConfig {
@Bean
CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
corsConfig.setMaxAge(8000L);
corsConfig.addAllowedMethod("PUT");
corsConfig.addAllowedHeader("Baeldung-Allowed");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.reactive.cors.webfilter.controllers;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/web-filter-and-more-on-annotated")
public class FurtherCorsConfigsController {
@DeleteMapping("/further-mixed-config-endpoint")
@CrossOrigin(methods = { RequestMethod.DELETE },
allowedHeaders = { "Baeldung-Other-Allowed" },
exposedHeaders = { "Baeldung-Other-Exposed" }
)
public Mono<String> corsEnabledHeaderExposedEndpoint() {
final String responseMessage = "CORS @CrossOrigin IS NOT EFFECTIVE with WebFilter!!!";
return Mono.just(responseMessage);
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.reactive.cors.webfilter.controllers;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/web-filter-on-annotated")
public class RegularRestController {
@PutMapping("/regular-put-endpoint")
public Mono<String> regularPutEndpoint() {
return Mono.just("Regular PUT endpoint");
}
@DeleteMapping("/regular-delete-endpoint")
public Mono<String> regularDeleteEndpoint() {
return Mono.just("Regular DELETE endpoint");
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.reactive.cors.webfilter.functional.handlers;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
@Component
public class CorsWithWebFilterHandler {
public Mono<ServerResponse> useHandler(final ServerRequest request) {
return ServerResponse.ok()
.body(Mono.just("Functional Endpoint"), String.class);
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.reactive.cors.webfilter.functional.routers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import com.baeldung.reactive.cors.webfilter.functional.handlers.CorsWithWebFilterHandler;
@Configuration
public class CorsWithWebFilterRouterFunctions {
@Bean
public RouterFunction<ServerResponse> responseHeaderRoute(@Autowired CorsWithWebFilterHandler handler) {
return RouterFunctions.route(RequestPredicates.PUT("/web-filter-on-functional/functional-endpoint"), handler::useHandler);
}
}

View File

@ -0,0 +1,147 @@
package com.baeldung.reactive.cors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CorsOnAnnotatedElementsLiveTest {
private static final String BASE_URL = "http://localhost:8081";
private static final String BASE_CORS_ON_METHODS_URL = "/cors-on-methods";
private static final String BASE_CORS_ON_CONTROLLER_URL = "/cors-on-controller";
private static final String CONTROLLER_CORS_ALLOWED_ORIGIN = "http://allowed-origin.com";
private static final String CORS_DEFAULT_ORIGIN = "http://default-origin.com";
private static WebTestClient client;
@BeforeAll
public static void setup() {
client = WebTestClient.bindToServer()
.baseUrl(BASE_URL)
.defaultHeader("Origin", CORS_DEFAULT_ORIGIN)
.build();
}
@Test
public void whenRequestingMethodCorsEnabledEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-enabled-endpoint")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "*");
}
@Test
public void whenPreflightMethodCorsEnabled_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-enabled-endpoint")
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "*");
response.expectHeader()
.valueEquals("Access-Control-Allow-Methods", "PUT");
response.expectHeader()
.exists("Access-Control-Max-Age");
}
@Test
public void whenRequestingMethodCorsDisabledEndpoint_thenObtainResponseWithoutCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-disabled-put-endpoint")
.exchange();
response.expectHeader()
.doesNotExist("Access-Control-Allow-Origin");
}
@Test
public void whenRequestingMethodCorsRestrictiveOrigin_thenObtainForbiddenResponse() {
ResponseSpec response = client.put()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-enabled-origin-restrictive-endpoint")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenPreflightMethodCorsRestrictiveOrigin_thenObtainForbiddenResponse() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-enabled-origin-restrictive-endpoint")
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenPreflightMethodCorsRestrictiveHeader_thenObtainResponseWithAllowedHeaders() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_METHODS_URL + "/cors-enabled-header-restrictive-endpoint")
.header("Access-Control-Request-Method", "PUT")
.header("Access-Control-Request-Headers", "Baeldung-Not-Allowed, Baeldung-Allowed")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Headers", "Baeldung-Allowed");
}
@Test
public void whenPreflightControllerCorsRegularEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_CONTROLLER_URL + "/regular-endpoint")
.header("Origin", CONTROLLER_CORS_ALLOWED_ORIGIN)
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CONTROLLER_CORS_ALLOWED_ORIGIN);
}
@Test
public void whenPreflightControllerCorsRestrictiveOrigin_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_CONTROLLER_URL + "/cors-enabled-origin-restrictive-endpoint")
.header("Origin", CONTROLLER_CORS_ALLOWED_ORIGIN)
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CONTROLLER_CORS_ALLOWED_ORIGIN);
}
@Test
public void whenPreflightControllerCorsRestrictiveOriginWithAnotherAllowedOrigin_thenObtainResponseWithCorsHeaders() {
final String anotherAllowedOrigin = "http://another-allowed-origin.com";
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_CONTROLLER_URL + "/cors-enabled-origin-restrictive-endpoint")
.header("Origin", anotherAllowedOrigin)
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", anotherAllowedOrigin);
}
@Test
public void whenPreflightControllerCorsExposingHeaders_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.options()
.uri(BASE_CORS_ON_CONTROLLER_URL + "/cors-enabled-exposed-header-endpoint")
.header("Origin", CONTROLLER_CORS_ALLOWED_ORIGIN)
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Expose-Headers", "Baeldung-Exposed");
}
}

View File

@ -0,0 +1,99 @@
package com.baeldung.reactive.cors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CorsOnGlobalConfigLiveTest {
private static final String BASE_URL = "http://localhost:8082";
private static final String BASE_REGULAR_URL = "/cors-on-global-config";
private static final String BASE_EXTRA_CORS_CONFIG_URL = "/cors-on-global-config-and-more";
private static final String BASE_FUNCTIONALS_URL = "/global-config-on-functional";
private static final String CORS_DEFAULT_ORIGIN = "http://allowed-origin.com";
private static WebTestClient client;
@BeforeAll
public static void setup() {
client = WebTestClient.bindToServer()
.baseUrl(BASE_URL)
.defaultHeader("Origin", CORS_DEFAULT_ORIGIN)
.build();
}
@Test
public void whenRequestingRegularEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_REGULAR_URL + "/regular-put-endpoint")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
}
@Test
public void whenRequestingRegularDeleteEndpoint_thenObtainForbiddenResponse() {
ResponseSpec response = client.delete()
.uri(BASE_REGULAR_URL + "/regular-delete-endpoint")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenPreflightAllowedDeleteEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.options()
.uri(BASE_EXTRA_CORS_CONFIG_URL + "/further-mixed-config-endpoint")
.header("Access-Control-Request-Method", "DELETE")
.header("Access-Control-Request-Headers", "Baeldung-Not-Allowed, Baeldung-Allowed, Baeldung-Other-Allowed")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
response.expectHeader()
.valueEquals("Access-Control-Allow-Methods", "PUT,DELETE");
response.expectHeader()
.valueEquals("Access-Control-Allow-Headers", "Baeldung-Allowed, Baeldung-Other-Allowed");
response.expectHeader()
.exists("Access-Control-Max-Age");
}
@Test
public void whenRequestAllowedDeleteEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.delete()
.uri(BASE_EXTRA_CORS_CONFIG_URL + "/further-mixed-config-endpoint")
.exchange();
response.expectStatus()
.isOk();
}
@Test
public void whenPreflightFunctionalEndpoint_thenObtain404Response() {
ResponseSpec response = client.options()
.uri(BASE_FUNCTIONALS_URL + "/cors-disabled-functional-endpoint")
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectStatus()
.isNotFound();
}
@Test
public void whenRequestFunctionalEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_FUNCTIONALS_URL + "/cors-disabled-functional-endpoint")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
}
}

View File

@ -0,0 +1,96 @@
package com.baeldung.reactive.cors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CorsOnWebFilterLiveTest {
private static final String BASE_URL = "http://localhost:8083";
private static final String BASE_REGULAR_URL = "/web-filter-on-annotated";
private static final String BASE_EXTRA_CORS_CONFIG_URL = "/web-filter-and-more-on-annotated";
private static final String BASE_FUNCTIONALS_URL = "/web-filter-on-functional";
private static final String CORS_DEFAULT_ORIGIN = "http://allowed-origin.com";
private static WebTestClient client;
@BeforeAll
public static void setup() {
client = WebTestClient.bindToServer()
.baseUrl(BASE_URL)
.defaultHeader("Origin", CORS_DEFAULT_ORIGIN)
.build();
}
@Test
public void whenRequestingRegularEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_REGULAR_URL + "/regular-put-endpoint")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
}
@Test
public void whenRequestingRegularDeleteEndpoint_thenObtainForbiddenResponse() {
ResponseSpec response = client.delete()
.uri(BASE_REGULAR_URL + "/regular-delete-endpoint")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenPreflightDeleteEndpointWithExtraConfigs_thenObtainForbiddenResponse() {
ResponseSpec response = client.options()
.uri(BASE_EXTRA_CORS_CONFIG_URL + "/further-mixed-config-endpoint")
.header("Access-Control-Request-Method", "DELETE")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenRequestDeleteEndpointWithExtraConfigs_thenObtainForbiddenResponse() {
ResponseSpec response = client.delete()
.uri(BASE_EXTRA_CORS_CONFIG_URL + "/further-mixed-config-endpoint")
.exchange();
response.expectStatus()
.isForbidden();
}
@Test
public void whenPreflightFunctionalEndpoint_thenObtain404Response() {
ResponseSpec response = client.options()
.uri(BASE_FUNCTIONALS_URL + "/functional-endpoint")
.header("Access-Control-Request-Method", "PUT")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
response.expectHeader()
.valueEquals("Access-Control-Allow-Methods", "PUT");
response.expectHeader()
.valueEquals("Access-Control-Max-Age", "8000");
}
@Test
public void whenRequestFunctionalEndpoint_thenObtainResponseWithCorsHeaders() {
ResponseSpec response = client.put()
.uri(BASE_FUNCTIONALS_URL + "/functional-endpoint")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", CORS_DEFAULT_ORIGIN);
}
}