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

Node.js无法接收POST JSON数据?预检请求跨域校验失败排查

问题原因分析

这个问题的核心是浏览器的跨域预请求(OPTIONS请求)没有被你的Node.js服务器正确处理,而PHP服务器和Postman则避开了这个限制:

  • 浏览器同源策略约束:当你从浏览器发送跨域POST请求(且请求头包含content-type: application/json这类非简单头)时,浏览器会自动先发送一个OPTIONS类型的预请求,用来确认服务器是否允许跨域操作。如果服务器没有正确响应这个预请求,浏览器就会抛出你看到的跨域错误。
  • Postman无限制:Postman作为API测试工具,不受浏览器同源策略的约束,它会直接发送POST请求,不会触发预请求流程,因此能正常拿到响应。
  • PHP服务器的自动处理:大概率是你的PHP服务器(比如搭配的Apache/Nginx)已经配置了CORS自动处理规则,或者你使用的PHP框架默认拦截并处理了OPTIONS请求,返回了符合要求的跨域头。
你的Node.js代码问题所在

你当前的代码只在POST请求的响应里设置了Access-Control-Allow-Origin头,但完全没有处理OPTIONS预请求。当浏览器发送OPTIONS请求时,服务器没有返回任何允许跨域的头信息,直接导致预请求失败,后续的POST请求也被浏览器拦截。

解决方案

推荐两种解决方式,优先选择第一种,更简洁可靠:

方式一:使用cors中间件(推荐)

Express官方推荐使用cors包来处理跨域问题,它会自动帮你处理OPTIONS预请求和所有跨域头的设置:

  1. 先安装cors包:
    npm install cors
    
  2. 修改你的Node.js代码:
    const express = require('express');
    const cors = require('cors');
    const app = express();
    
    // 全局启用CORS,所有请求都会自动处理跨域逻辑
    app.use(cors());
    app.use(express.json());
    
    app.post('/post', function(req, res){
      res.send(req.body);
    })
    
    // 启动服务器监听端口
    app.listen(3010, () => {
      console.log('Server running on port 3010');
    })
    

方式二:手动处理OPTIONS请求

如果你不想额外安装依赖,可以手动处理OPTIONS请求,并在所有请求中设置完整的跨域头:

const express = require('express');
const app = express();
app.use(express.json());

// 处理所有OPTIONS预请求,返回允许跨域的头信息
app.options('*', function(req, res){
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.sendStatus(200);
});

// 处理POST请求,同时设置跨域头
app.post('/post', function(req, res){
  res.header('Access-Control-Allow-Origin', '*');
  res.send(req.body);
})

app.listen(3010, () => {
  console.log('Server running on port 3010');
})

前端代码小修正

你的前端AJAX还有个细节问题:直接传对象作为data时,jQuery默认会把它编码成x-www-form-urlencoded格式,但你设置了content-type: application/json,所以需要把数据转成JSON字符串:

function callAjax(){
  jQuery.ajax({
    method: 'POST',
    url:'http://localhost:3010/post',
    headers: {
      "content-type": "application/json"
    },
    data: JSON.stringify({ email:'fake@mail.com' }), // 转成JSON字符串匹配请求头
    success: function(data){
      console.log(data);
    },
    error: function(err){
      console.log(err);
    }
  });
}

这样修改后,你的跨域请求就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:41:42