React + Plumber API POST请求遭遇CORS错误求助
解决React + R Plumber架构下POST请求的CORS预请求失败问题
问题描述
React应用运行在http://localhost:5173,Plumber API运行在http://localhost:8000。GET请求正常,但POST请求时Chrome控制台报错:
Access to XMLHttpRequest at 'http://localhost:8000/addMappingItem' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
排查分析
核心问题是CORS中间件未正确生效:
- 在
run_local.R中定义了corsMiddleware函数,但plumber_api.R的钩子注册代码无法访问该函数(两个脚本执行环境隔离),导致CORS钩子注册失败。 - 浏览器发送的OPTIONS预请求未被处理,返回非204的错误状态码,触发CORS拦截机制。
修复方案
方案1:在run_local.R中直接注册CORS钩子
统一在API启动脚本中注册中间件,避免跨环境引用问题:
- 更新
run_local.R的API启动部分:
# Run the Plumber API pr <- plumb("plumber_api.R") # 注册CORS预路由钩子 pr$registerHooks(list( preroute = corsMiddleware )) pr$run(port=8000)
- 删除
plumber_api.R中的以下代码块(消除重复注册冲突):
#* @plumber function(pr) { pr$registerHooks(list( preroute = corsMiddleware )) return(pr) }
方案2:将CORS中间件移至plumber_api.R中
把中间件定义移到API逻辑脚本内,确保钩子注册时能正确引用:
- 在
plumber_api.R的开头添加CORS中间件定义:
# CORS POLICY MIDDLEWARE: corsMiddleware <- function(req, res) { res$setHeader('Access-Control-Allow-Origin', '*') res$setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') res$setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With") # Handle preflight requests if (req$REQUEST_METHOD == "OPTIONS") { res$status <- 204 return(res) } plumber::forward() }
- 删除
run_local.R中的corsMiddleware定义,保留plumber_api.R里的钩子注册代码。
额外优化:简化POST请求体解析
Plumber会自动解析Content-Type: application/json的请求体到req$body,无需手动处理req$postBody,可简化/addMappingItem接口代码:
#* Adds a new element to the Mapping Data Table #* @post /addMappingItem #* @serializer json function(req){ parsedData <- req$body # 自动解析JSON请求体 parsedDataTable <- as.data.table(parsedData) print(parsedDataTable) names(parsedDataTable) <- c("CarModel", "CarBrand") finalDataTable <- parsedDataTable[, ':=' ( CarName_beginning = paste0(CarModel, " ", CarBrand), CarModel_prep = tolower(CarModel), LetterNumberCarName = nchar(CarModel) )] print(finalDataTable) dbWriteTable(conn = dbPool, name = "Mapping_cars", value = finalDataTable, append = TRUE, row.names = FALSE) return(list(message = "Mapping item added successfully!")) }
验证步骤
- 重启Plumber API服务
- 在React应用中触发POST请求,检查Chrome控制台是否仍有CORS错误
- 查看Network面板,确认OPTIONS请求返回状态码204,POST请求返回200
内容的提问来源于stack exchange,提问作者Skof
相关产品推荐
相关产品推荐

