You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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启动脚本中注册中间件,避免跨环境引用问题:

  1. 更新run_local.R的API启动部分:
# Run the Plumber API
pr <- plumb("plumber_api.R")

# 注册CORS预路由钩子
pr$registerHooks(list(
  preroute = corsMiddleware
))

pr$run(port=8000)
  1. 删除plumber_api.R中的以下代码块(消除重复注册冲突):
#* @plumber
function(pr) {
  pr$registerHooks(list(
    preroute = corsMiddleware
  ))
  return(pr)
}

方案2:将CORS中间件移至plumber_api.R中

把中间件定义移到API逻辑脚本内,确保钩子注册时能正确引用:

  1. 在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()
}
  1. 删除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!"))
}

验证步骤

  1. 重启Plumber API服务
  2. 在React应用中触发POST请求,检查Chrome控制台是否仍有CORS错误
  3. 查看Network面板,确认OPTIONS请求返回状态码204,POST请求返回200

内容的提问来源于stack exchange,提问作者Skof

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 19:17:16