Search code examples
javaspring-bootcorsspring-webfluxsame-origin-policy

WebTestClient - CORS with Spring Boot and Webflux


I have Vuejs frontend and a Spring Boot Webflux controller. Now the browser is complaining with CORS when doing a call to Spring Boot.

Access to XMLHttpRequest at 'https://...' from origin 'https://...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

To enable CORS I tried to use the @CrossOrigin annotation as described here: https://www.baeldung.com/spring-webflux-cors

But it didn't help and somehow Spring does not send the CORS headers back in the response even with the @CrossOrigin annotation in the controller.

I also tried with the WebTestClient as described in the Bealdung tutorial and it confirms the header is not there:

java.lang.AssertionError: Response header 'Access-Control-Allow-Origin' expected:<[*]> but was:<null>

> OPTIONS /cors-enabled-endpoint
> WebTestClient-Request-Id: [1]
> Origin: [http://any-origin.com]
> Access-Control-Request-Method: [GET]

No content

< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Vary: [Origin, Access-Control-Request-Method, Access-Control-Request-Headers]

0 bytes of content (unknown content-type).

If I test with response.expectHeader().exists("Access-Control-Allow-Origin"); I get:

java.lang.AssertionError: Response header 'Access-Control-Allow-Origin' does not exist

Any Idea why CORS configuration as described in the link above does not work? I also tried Enabling CORS on the Global Configuration and Enabling CORS with a WebFilter. But nothing seems to work.


Solution

  • The solution was to use following configuration for the WebTestClient:

    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    @AutoConfigureWebTestClient
    
    class MyTestClass {
    
        @Autowired
        private WebTestClient webTestClient;
    
        @Test
        void corsTest() {
            ResponseSpec response = webTestClient.get()
                    .uri("/cors-enabled-endpoint")
                    .header("Origin", "http://any-origin.com")
                    .exchange();
    
            response.expectHeader()
                    .valueEquals("Access-Control-Allow-Origin", "*");
        }
    
    }
    

    And I also needed to add the spring-boot-starter-web dependency, which is very strange because I am using only Webflux. But without it the test still fails with IllegalArgumentException: Actual request scheme must not be null.

    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    Now, the test is green!