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)
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()
}