如何使用 graphql-kotlin 在 Spring Boot 服务器中添加 CORS 标头?
Posted
技术标签:
【中文标题】如何使用 graphql-kotlin 在 Spring Boot 服务器中添加 CORS 标头?【英文标题】:How do you handle adding a CORS header in a Spring Boot server with graphql-kotlin? 【发布时间】:2020-04-23 14:01:29 【问题描述】:我正在使用由 Expedia 创建和开源的GraphQL Kotlin library 构建一个简单的 Spring Server 项目。我有一个正在运行的后端,正在与数据存储区通信,并且我能够通过 Playground 发送查询来获取数据。
当我尝试从我的 React 前端(使用 Apollo)连接时,由于 CORS 问题,初始 OPTIONS 请求会收到 404 响应。我对 Spring Boot 比较陌生,在 SO 和其他地方记录了很多潜在的方法。
如何拦截响应并添加适当的 Access-Control-Allow-Origin 标头?
【问题讨论】:
【参考方案1】:在尝试了上述许多方法后,我找到了一种适用于我的特定变量组合的方法。
例如,这些不起作用:
-
覆盖
addCorsMappings
的WebFluxConfigurer组件
功能
@CrossOrigin
查询函数上的注解
将 spring boot actuator lib 添加到项目中,并将 management.endpoints.web.cors 配置添加到 application.yml,每 the Spring documentation
根据这个 SO 问题,最终对我有用的是自定义 WebFilter 子类:Enable CORS in Spring 5 Webflux?
还有this tutorial,它详细说明了 Spring Boot 的一般工作原理。
【讨论】:
【参考方案2】:你可以这样做:
@Bean
@Profile("!production")
fun corsFilter(): CorsWebFilter = CorsWebFilter(
UrlBasedCorsConfigurationSource().apply
registerCorsConfiguration(
"/**",
CorsConfiguration().apply
allowCredentials = true
allowedOrigins = listOf("*")
allowedHeaders = listOf("*")
allowedMethods = listOf("*")
)
)
【讨论】:
【参考方案3】:对我来说(使用与您相同的技术),创建自定义过滤器组件 (CorsFilter) 是所有其他选项中效果最好的:
我的配置示例:
@Component
class CorsFilter: WebFilter
@Value("\$cors.allowed_origin")
lateinit var allowedOrigin: String
override fun filter(ctx: ServerWebExchange, chain: WebFilterChain): Mono<Void>
ctx.response.headers.add("Access-Control-Allow-Origin", allowedOrigin)
ctx.response.headers.add("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS")
ctx.response.headers.add("Access-Control-Allow-Credentials", "true")
ctx.response.headers.add("Access-Control-Allow-Headers", "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range, Authorization")
return when
ctx.request.method == HttpMethod.OPTIONS ->
ctx.response.headers.add("Access-Control-Max-Age", "1728000")
ctx.response.statusCode = HttpStatus.NO_CONTENT
Mono.empty()
else ->
ctx.response.headers.add("Access-Control-Expose-Headers", "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range")
chain.filter(ctx)
注意:allowedOrigin
变量取自 applications.properties 文件
【讨论】:
【参考方案4】:只有在 spring boot-kotlin 服务器中添加下一个配置才能使用 React 和 Apollo:
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.web.cors.reactive.CorsUtils
import org.springframework.web.server.WebFilter
import reactor.core.publisher.Mono
@Configuration
class ReactiveConfigurations
companion object
const val ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN"
const val ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS"
const val ALLOWED_ORIGIN = "*"
const val MAX_AGE = "3600"
@Bean
fun corsFilter(): WebFilter
return WebFilter ctx, chain ->
val request = ctx.request
if (CorsUtils.isCorsRequest(request))
val response = ctx.response
val headers = response.headers
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN)
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS)
headers.add("Access-Control-Max-Age", MAX_AGE)
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS)
if (request.method === HttpMethod.OPTIONS)
response.statusCode = HttpStatus.OK
return@WebFilter Mono.empty<Void>()
chain.filter(ctx)
【讨论】:
以上是关于如何使用 graphql-kotlin 在 Spring Boot 服务器中添加 CORS 标头?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 ktor 框架的 graphql-kotlin 进行字段级解析器
Pygame错误:self.spritedict [spr] = surface_blit(spr.image,spr.rect)
使用Spire组件抛出异常The type initializer for 'spr857' threw an exception