如何在node.js的express.js框架中启用跨域资源共享(CORS)


101

我正在尝试在node.js中构建Web服务器,该服务器将支持跨域脚本编写,同时仍从公共目录中提供静态文件。我正在使用express.js,但我不确定如何允许跨域脚本(Access-Control-Allow-Origin: *)。

我看到了这篇文章,但对我没有帮助。

var express = require('express')
  , app = express.createServer();

app.get('/', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(app.router);
});

app.configure('development', function () {

    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {


    var oneYear = 31557600000;
    //    app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

注意app.all vs app.get。这是OPTIONS请求未得到GET
Shimon Doodkin

有关支持CORS的简单节点,静态Web 服务器的示例,请参见local-web-server
Lloyd

有关更多信息,请参见enable-cors.org/server_apache.html
Mostafa

Answers:


159

查看来自enable-cors.org的示例

在node.js上的ExpressJS应用中,对路由执行以下操作:

app.all('/', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
 });

app.get('/', function(req, res, next) {
  // Handle the get for this route
});

app.post('/', function(req, res, next) {
 // Handle the post for this route
});

首次呼叫(app.all)应该在应用中的所有其他路由(或至少要启用CORS的路由)之前进行。

[编辑]

如果您还希望显示静态文件的标头,请尝试执行此操作(确保在调用之前use(express.static())

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

我用您的代码对此进行了测试,并从public目录中获取了资产的标头:

var express = require('express')
  , app = express.createServer();

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With");
      next();
    });
    app.use(app.router);
});

app.configure('development', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

当然,您可以将该功能打包到一个模块中,以便可以执行以下操作

// cors.js

module.exports = function() {
  return function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
  };
}

// server.js

cors = require('./cors');
app.use(cors());

嘿,谢谢您的回复。我按照您的建议做了(第一部分,但在请求标头中仍然看不到任何不同),我已经在上面附加了当前代码。您能解释一下我如何将其余的解决方案集成到其中吗?
盖伊2012年

1
我很惊讶,因为你use荷兰国际集团app.router之前express.static,它不会修改对静态文件的头部; 无论如何,我已经更新了答案,以便可以使用。
Michelle Tilley 2012年

谢谢!我知道你是对的。从服务器获取的资产带有请求的标头。我可能不清楚我的真实问题。我正在尝试使用get命令对外部服务器进行API调用。那就是我得到错误的地方:XMLHttpRequest无法加载SOMEURL.com。Access-Control-Allow-Origin不允许源localhost:8888
盖伊2012年

我可能会误会。您是否在SOMEURL.com上控制服务器?
米歇尔·提里(Michelle Tilley)2012年

抱歉,我现在完全理解您的回答。非常感谢。感谢您的帮助:)
盖伊

58

遵循@Michelle Tilley解决方案后,起初显然不适用于我。不知道为什么,也许我正在使用chrome和不同版本的节点。经过一些小的调整后,它现在对我有用。

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

如果有人面临与我类似的问题,这可能会有所帮助。


注意app.all vs app.get。这是OPTIONS请求无法获取
Shimon Doodkin

这对我有用(我正在使用Backbone获取对象)。我试图弄清楚它是否可以在IE 8中运行...似乎应该如此,但是我不知道此“ XDomainRequest”是否需要任何特殊的东西... developer.mozilla.org/zh-美国/文档/ HTTP /…
亚当爱

未来用户的一些信息:我将域名重定向到一个heroku存储库,这就是我遇到此问题的原因。无论如何,第一个答案在本地有效,但在我将其推送到heroku之后却没有。然而,这个答案在推到heroku之后仍然有效。
克里斯·霍伦贝克

@KrisHollenbeck在heroku上这对我不起作用,您还做其他事情吗?
本·克雷格

@BenCraig,不,但是在第一次尝试后它实际上停止了为我工作。所以我实际上仍然有这个问题。
克里斯·霍伦贝克

11

尝试使用此cors npm模块。

var cors = require('cors')

var app = express()
app.use(cors())

该模块提供了许多功能来微调cors设置,例如域白名单,为特定的api启用cors等。


2

我用这个:

var app = express();

app
.use(function(req, res, next){
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With');
    next();
})
.options('*', function(req, res, next){
    res.end();
})
;

h.readFiles('controllers').forEach(function(file){
  require('./controllers/' + file)(app);
})
;

app.listen(port);
console.log('server listening on port ' + port);

此代码假定您的控制器位于controllers目录中。此目录中的每个文件应如下所示:

module.exports = function(app){

    app.get('/', function(req, res, next){
        res.end('hi');
    });

}

1

推荐使用cors express模块​​。这样,您就可以将域列入白名单,允许/限制域专门用于路由等,


0

Access-Control-Allow-Credentials: true如果要通过“凭据”使用“ cookie”,则必须设置

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

0
app.use(function(req, res, next) {
var allowedOrigins = [
  "http://localhost:4200"
];
var origin = req.headers.origin;
console.log(origin)
console.log(allowedOrigins.indexOf(origin) > -1)
// Website you wish to allow to
if (allowedOrigins.indexOf(origin) > -1) {
  res.setHeader("Access-Control-Allow-Origin", origin);
}

// res.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");

// Request methods you wish to allow
res.setHeader(
  "Access-Control-Allow-Methods",
  "GET, POST, OPTIONS, PUT, PATCH, DELETE"
);

// Request headers you wish to allow
res.setHeader(
  "Access-Control-Allow-Headers",
  "X-Requested-With,content-type,Authorization"
);

// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader("Access-Control-Allow-Credentials", true);

// Pass to next layer of middleware
next();

});

将此代码添加到index.js或server.js文件中,并根据需要更改允许的原始数组。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.