脊椎、node.js (express) 和 Access-Control-Allow-Origin

Posted

技术标签:

【中文标题】脊椎、node.js (express) 和 Access-Control-Allow-Origin【英文标题】:spine, node.js (express) and Access-Control-Allow-Origin 【发布时间】:2012-04-22 02:51:30 【问题描述】:

我正在本地电脑上开发一个应用程序。前端应该使用 spinjs 构建,后端 API 应该使用 node.js。 Spine 在端口 9294 上运行,node.js 在端口 3000 上运行。 在 Spine 中,我在模型中添加了以下内容:

@url: "http:localhost:3000/posts"

在我的快递服务器中

app.get('/posts', function(req, res)
  console.log("giving ALL the posts");
  res.header("Access-Control-Allow-Origin", "*")
  res.json(posts);
);

但我总是在 chrome 中收到以下错误:

XMLHttpRequest cannot load http://localhost:3000/posts. Origin http://localhost:9294 is not allowed by Access-Control-Allow-Origin.

我必须做什么才能正确访问我的 api?我虽然在响应中添加标题确实可以解决问题。

【问题讨论】:

您是否检查了响应标头以确认标头确实已设置?此外,jQuery 使用 'OPTIONS' HTTP 命令来检测预授权;确保 express 也响应该 HTTP 动词 老实说,我的请求似乎永远不会到达我的 node.js 服务器。在将任何内容发送到客户端之前,我在 app.get() 中添加了一个调试语句。直接通过 url 访问我的 api 时,我可以看到该语句,但通过 spin 访问时看不到 你应该使用像 charles 这样的东西来确保这种情况发生。我们在这里做了很多 x 域的事情,直到您看到没有设置标头,这令人沮丧。 【参考方案1】:

app.get 只会响应GET 请求。如果浏览器使用OPTIONS 请求对其进行预检,express 将发送错误,因为它没有任何侦听器来处理这些请求。尝试在您的代码之外添加此代码,看看它是否有效:

app.options('/posts', function(req, res)
  console.log("writing headers only");
  res.header("Access-Control-Allow-Origin", "*");
  res.end('');
);

另请注意:如果您在请求中发送 cookie (withcredentials=true),则 Access-Control-Allow-Origin 标头不能是 *,它必须是浏览器自动添加的 Origin 标头中的确切值像这样的ajax请求:

res.header("Access-Control-Allow-Origin", req.headers.origin);

这是出于安全原因 - 如果您正在执行需要 cookie 的操作,那么您更有可能需要实际检查 origin 是否是允许的网站,以避免 CSRF attacks。

【讨论】:

【参考方案2】:

此中间件将允许 CORS 使用 Express,关键是检测预检请求 OPTIONS 并返回响应以避免 404 或重复的数据库查询。 见资源:http://cuppster.com/2012/04/10/cors-middleware-for-node-js-and-express/

var methodOverride = require('method-override');
app.use(methodOverride());

// ## CORS middleware
// see: http://***.com/questions/7067966/how-to-allow-cors-in-express-nodejs
var allowCrossDomain = function(req, res, next) 
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');

    // intercept OPTIONS method
    if ('OPTIONS' == req.method) 
      res.send(200);
    
    else 
      next();
    
;
app.use(allowCrossDomain);

【讨论】:

methodOverride 从版本 4 开始不再与 Express 捆绑,因此您需要在 package.json 中包含“method-override”,然后使用 app.use(express.methodOverride()) 代替 var methodOverride = require('method-override'); app.use(methodOverride());跨度>

以上是关于脊椎、node.js (express) 和 Access-Control-Allow-Origin的主要内容,如果未能解决你的问题,请参考以下文章

node.js 和 express 的区别

Node js之Express初步介绍和安装

UnhandledPromiseRejectionWarning、Express.js 和 Node.js

开源 Node.js(和 Express)项目 [关闭]

使用 Node.js 和 Express 发布时如何访问请求正文?

Express 和 node.js 中的 HTML?