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

React+Node.js跨域POST请求失败问题求助

解决React前端与原生Node.js后端的CORS POST请求问题

问题场景

  • React前端运行在localhost:3000,原生Node.js后端运行在localhost:4000
  • GET请求可正常获取数据,但POST请求无法向数据库写入数据
  • POSTMAN测试POST请求正常,但前端控制台报CORS相关错误

前端代码

const sendData = async (event: any): Promise<void> => {
    console.log("hello");
    event.preventDefault();
    const response = await fetch(`${_DATA_URL_}`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(employeeForm),
    });
    const data = await response.json();
    console.log(data);
  };

后端路由代码

const Router = (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Content-Type, Accept, Origin, Authorization"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, PATCH, OPTIONS"
  );
  console.log("hello"); //debug
  if (req.method === "GET") {
    if (req.url === "/api/employees") {
      getEmployees(req, res);
    } else if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];

      getEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "POST") {
    if (req.url === "/api/employees") {
      createEmployee(req, res);
    } else {
      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "DELETE") {
    if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];
      deleteEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "PUT") {
    if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];
      updateEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
};

问题原因

浏览器对非简单请求(比如设置了Content-Type: application/json的POST请求)会先发一个OPTIONS预检请求,用来确认后端是否允许跨域请求。当前你的后端路由没有处理OPTIONS请求的逻辑,导致预检请求得不到正确响应,浏览器拦截了后续的POST请求,从而触发CORS错误。

而GET请求属于简单请求,浏览器不会发送预检OPTIONS,直接发送请求,后端设置的CORS头能正常生效,所以GET可以正常工作。Postman不会发送预检请求,所以POST测试正常。

解决方案

在后端路由最顶部添加OPTIONS请求的处理逻辑,直接返回200状态码即可,因为预检请求只需要验证CORS配置,不需要处理业务逻辑:

修改后的后端路由代码

const Router = (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Content-Type, Accept, Origin, Authorization"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, PATCH, OPTIONS"
  );

  // 处理OPTIONS预检请求
  if (req.method === "OPTIONS") {
    res.writeHead(200);
    res.end();
    return; // 终止后续逻辑
  }

  console.log("hello"); //debug
  if (req.method === "GET") {
    if (req.url === "/api/employees") {
      getEmployees(req, res);
    } else if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];

      getEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "POST") {
    if (req.url === "/api/employees") {
      createEmployee(req, res);
    } else {
      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "DELETE") {
    if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];
      deleteEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
  if (req.method === "PUT") {
    if (req.url.match(/\/api\/employees\/(\w{4}-?){3}/)) {
      const requestID = req.url.split("/")[3];
      updateEmployee(req, res, requestID);
    } else {
      res.statusCode = 404;

      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ message: `Error : ${req.url} not found !` }));
    }
  }
};

添加这段OPTIONS处理逻辑后,浏览器的预检请求会得到正常响应,后续的POST请求就能顺利发送到后端,完成数据写入操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:26:05