I am attempting to use CorsWebFilter in a spring-boot application using Kotlin and webflux. Here is the code:

import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfiguration;

@Configuration
public class CorsConfiguration {

  @Bean
    fun corsWebFilter(): CorsWebFilter {
        val corsConfig = CorsConfiguration()
        corsConfig.addAllowedOrigin("http://localhost:3000")
        corsConfig.addAllowedMethod("GET")
        corsConfig.addAllowedMethod("PUT")
        corsConfig.addAllowedMethod("POST")
        corsConfig.addAllowedMethod("OPTION")
        corsConfig.addAllowedMethod("DELETE")
        corsConfig.addAllowedHeader("x-requested-with")
        corsConfig.addAllowedHeader("authorization")
        corsConfig.addAllowedHeader("Content-Type")
        corsConfig.addAllowedHeader("credential")
        corsConfig.addAllowedHeader("X-XSRF-TOKEN")

        val source = UrlBasedCorsConfigurationSource().apply {
            registerCorsConfiguration("/**", corsConfig)
        }
        return CorsWebFilter(source) //type mismatch here
    }
}   

The issue is that I have the following error -

Type mismatch: inferred type is UrlBasedCorsConfigurationSource but CorsConfigurationSource was expected

However, according to the documentation (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/cors/UrlBasedCorsConfigurationSource.html)

All Implemented Interfaces:
CorsConfigurationSource

Reading the source code, it would appear that UrlBasedCorsConfigurationSource should be accepted (https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/cors/reactive/CorsWebFilter.java#L54)

The spring documentation found here (https://docs.spring.io/spring-framework/docs/5.0.2.RELEASE/spring-framework-reference/web-reactive.html) also has UrlBasedCorsConfigurationSource being passed to CorsWebFilter (please see 1.7.4 Cors Web Filter)

Am I wrong in assuming that since UrlBasedCorsConfigurationSource implements CorsConfigurationSource that CorsWebFilter should accept it? If so, what is the proper way of using the WebFilter?

Comment From: rstoyanchev

I'm not sure what the issue is but it seems to be Kotlin specific. This works fine:

CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.addAllowedOrigin("http://localhost:3000");
// ...

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);

CorsWebFilter webFilter = new CorsWebFilter(source);

Comment From: rstoyanchev

I've also tried your example and unable to reproduce the issue.

Comment From: patientplatypus6

This is what I'm seeing in my IDE (and is duplicated in terminal on running)

Screenshot from 2021-07-16 10-29-10

This is in a top level package file and the Kotlin code is the same as the Java code as far as I can tell (it is a very simple handler).

Maybe it has to do with my gradle file (that is the only thing I can think of). For the moment I've managed to get around the problem by just writing @CrossOrigin everywhere, but it does mean that in order to handle sessions I've had to spin up a node server to handle redis...which is frustrating. I'm pasting my gradle code below if there's something that's immediately apparent, but otherwise please consider this not so important but a possible bug.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.5.2"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    application
    kotlin("jvm") version "1.5.20"
    kotlin("plugin.spring") version "1.5.20"
}

application {
  mainClass.set("platypus.bookstore.BookstoreApplicationKt") 
}

group = "platypus.bookstore.spring-boot"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
    // url "https://kotlin.bintray.com/kotlinx"
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("com.fasterxml.jackson.core:jackson-databind:2.12.4")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.+")
    implementation("org.springframework.security:spring-security-crypto:5.5.1")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1")
    implementation("org.json:json:20210307")
    runtimeOnly("com.h2database:h2")
    runtimeOnly("dev.miku:r2dbc-mysql")
    runtimeOnly("io.r2dbc:r2dbc-h2")
    runtimeOnly("mysql:mysql-connector-java")
    developmentOnly("org.springframework.boot:spring-boot-devtools")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}