Search code examples
javaspring-bootkotlincorspreflight

CORS Preflight Error In Kotlin and Springboot


Here is the absolute minimal test case for the following error:

Access to fetch at 'http://localhost:8080/comment' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

First, I download the following project from https://start.spring.io/

spring-kotlin-initializer

The only two dependencies are Spring Web and Rest Repositories

I then add the following to my DemoApplication.kt file:

package com.example.demo //original line

import org.springframework.boot.autoconfigure.SpringBootApplication //original line
import org.springframework.boot.runApplication //original line

import org.springframework.web.bind.annotation.GetMapping //added line
import org.springframework.web.bind.annotation.PostMapping //added line
import org.springframework.web.bind.annotation.RestController //added line
import org.springframework.web.bind.annotation.CrossOrigin //added line
import org.springframework.web.bind.annotation.RequestMapping //added line
import org.springframework.web.bind.annotation.RequestBody //added line

@SpringBootApplication //original line
class DemoApplication //original line

fun main(args: Array<String>) { //original line
    runApplication<DemoApplication>(*args) //original line
} //original line

//below all added lines

@RestController
@CrossOrigin(origins = ["http://localhost:3000"], maxAge=3600, allowCredentials = "true")
@RequestMapping("/test")
public class RequestTest{
    
    @GetMapping
    // @CrossOrigin(origins = ["http://localhost:3000"], maxAge=3600, allowCredentials = "true")
    fun stringfunc():String{
        println("inside the index of requesttest")
        return "some string"
    }

    @RequestMapping("/comment")
    // @CrossOrigin(origins = ["http://localhost:3000"], maxAge=3600, allowCredentials = "true")
    fun getComment() : String {
        val comment: String = "i hope this works"
        return comment
    }

}

Here is the pom.xml file which is unmodified from the downloaded application -

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
        <kotlin.version>1.5.20</kotlin.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <configuration>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <compilerPlugins>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

</project>

The build output shows no errors and that the server is running.

My javascript fetch request is -

const fetchrequest = () => { 
  fetch('http://localhost:8080/comment')
  .then(response => response.json())
  .then(data => console.log(data))
}

This should be the absolute minimal application that @CrossOrigin should work on. I don't know what the issue is.


Solution

  • Try this:

    @SpringBootApplication
    class KotlinServerApplication
    
    fun main(args: Array<String>) {
        runApplication<KotlinServerApplication>(*args)
    }
    
    @RestController
    @CrossOrigin(origins = ["http://localhost:3000"], maxAge=3600, allowCredentials = "true")
    public class RequestTest{
        
        @GetMapping("/comment")
        fun getComment() : Comment {
            val comment = Comment(
                author = "test",
                content = "test",
            )
            return comment
        }
    
    }