* Added changes for BAEL-1922 Enable CORS in Spring Webflux (#4724)
This commit is contained in:
parent
4288b6cc90
commit
baab69a43a
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue