带有预检的 Node.JS 中的跨域 POST 请求?

Posted

技术标签:

【中文标题】带有预检的 Node.JS 中的跨域 POST 请求?【英文标题】:Cross-domain POST request in Node.JS with preflight? 【发布时间】:2015-12-13 17:11:23 【问题描述】:

亲爱的,请考虑一下我刚刚开始使用 Node.js。

我正在尝试从 html 表单获取跨域表单数据以在 Node.js 服务器中进行解析。我已经能够使用简单的 POST 数据来做到这一点,而不是需要预检的 POST 请求。

我正在cloud9 app servers 上运行节点代码。 我还使用Cors 模块来处理请求。该模块适用于简单的请求(测试here 以查看简单的请求工作),但是对于需要预检的请求,我从 Chrome 检查器控制台获得此结果。

XMLHttpRequest cannot load https://nms-motaheri-1.c9.io:8080/mail. 
The request was redirected to 'https://c9.io:8080/api/nc/auth?.....SHORTENED', 
which is disallowed for cross-origin requests that require preflight.

这是我的 server.js 代码:

// Define dependencies 
var express = require('express')
  , cors = require('cors')
  , app = express()
  , parse_post = require("parse-post");

// Core module config 
var corsOptions = 
  origin: '*',
  preflightContinue: true  // <- I am assuming this is correct 
;

app.use(cors(corsOptions));

// Respond to option request with HTTP 200
// ?? Why is this not answering my OPTION requests sufficiently ??
app.options('*',function(req,res)
  res.send(200);
);

// Give a hello world response to all GET requests 
app.get('/',function(req,res)
  res.sendFile(__dirname + '/index.html');
);

// Handle all POST requests to /mail
app.post('/mail', parse_post(function(req, res) 
    console.log(req.body);
    res.json(msg: 'This is CORS-enabled for all origins!');
  )
);

// Listen on default Cloud9 port which is 8080 in this case
app.listen(process.env.PORT, function()
  console.log('CORS-enabled web server listening on port ' + process.env.PORT);
);

为什么会发生这种情况?如何通过飞行前令人满意地回答我的 POST 的 OPTION 请求?

谢谢您,我们将不胜感激。

这是 Chrome 开发工具中的发布请求和响应:

【问题讨论】:

您能从 Chrome 的 DevTools 的网络标签中发布请求和响应标头吗? 嗨,我已经编辑了这个问题,以便在最后添加一个屏幕截图 - 谢谢。 阅读此页面:blog.dzhuvinov.com/?p=979 - 具体来说:“所以请记住,重定向 URL 还必须包含 Access-Control-Allow-Origin 标头,否则浏览器将停在那里与其尝试的跨域请求。” 【参考方案1】:

原来问题的一部分是 cloud9 服务器设置为私有,使得这些请求全部重定向。

在公开服务器后,重定向停止。但是,我收到一条错误消息,指出 Node.js 服务器没有任何 Access-Control-Allow-Origin 标头来允许来自我的跨域域的请求。我注意到没有预检请求的“简单”会通过。因此,与其试图理解为什么它不接受我在 Node.js 端的 allow-all-origin-configuration,我决定序列化 POST 数据以摆脱预检要求并将我的角度请求中的数据类型更改为普通文本。

要摆脱预检,首先要摆脱任何 POST 标头配置(缓存等),确保您的请求 Content-Type 是纯文本,并确保您的实际内容也是纯文本。因此,如果它在 JSON 中,则在使用 POST 发送之前在 jQuery 中对其进行序列化。

这就是我的新 Angular Post 请求代码的样子:

sendEmail: function(email) 
    var config = 
        headers:  
            'Content-Type': 'text/plain'
        
    ;
    var POSTDATA= JSON.stringify(POSTDATAJSON);
    return $http.post(POSTURL, POSTDATA, config)

在 Node.js 中,我使用的是 cors Node.js 模块:

app.post('/mail', parse_post(function(req, res) 
    var postReq = JSON.parse(Object.keys(req.body)); 
));

【讨论】:

以上是关于带有预检的 Node.JS 中的跨域 POST 请求?的主要内容,如果未能解决你的问题,请参考以下文章

护照Facebook登录中的“对于需要预检的跨域请求是不允许的”错误?

发送带有自定义 HTTP 标头的跨域请求时禁用预检 OPTION 请求

该请求被重定向到“https://..com/site/login?”,这对于需要预检的跨域请求是不允许的

我正在使用 angularjs 和 django-cors-headers 然后给出“这对于需要预检的跨域请求是不允许的。”

前端跨域 OPTIONS 预检问题

preflight request预检请求