我试图在使用Express.js web框架的Node.js应用程序中支持CORS。我已经阅读了谷歌关于如何处理这个问题的小组讨论,并阅读了一些关于CORS如何工作的文章。首先,我这样做(代码是用CoffeeScript语法写的):

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

这似乎不管用。似乎我的浏览器(Chrome)没有发送最初的选项请求。当我刚刚更新了块的资源,我需要提交一个跨起源GET请求:

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

它工作(在Chrome)。这也适用于Safari。

我听说……

在实现CORS的浏览器中,每个跨源GET或POST请求之前都有一个OPTIONS请求,用于检查GET或POST是否正常。

所以我的主要问题是,为什么这种情况在我身上没有发生?为什么我的app。options块没有被调用?为什么我需要在我的主app.get块设置标题?


当前回答

前段时间,我遇到了这个问题,所以我这样做是为了在我的nodejs应用程序中允许CORS:

首先你需要使用以下命令安装cors:

npm install cors --save

现在将以下代码添加到应用程序的启动文件中,如(app.js或server.js)

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);

其他回答

这与Pat的回答相似,不同之处在于我用res.sendStatus(200)结束;而不是next();

代码将捕获方法类型OPTIONS的所有请求,并返回access-control-headers。

app.options('/*', (req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
    res.sendStatus(200);
});

代码接受问题中要求的所有来源的CORS。但是,最好将*替换为特定的来源,即http://localhost:8080,以防止误用。

因为我们使用的是app.options-method而不是app.use-method,所以我们不需要做这样的检查:

req.method === 'OPTIONS'

我们可以从其他答案中看到。

我在这里找到了答案:http://johnzhang.io/options-request-in-express。

保持相同的路由思想。我使用这个代码:

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

类似于http://enable-cors.org/server_expressjs.html的例子

为了回答您的主要问题,CORS规范只要求在POST或GET中有任何非简单内容或标头时将OPTIONS调用放在POST或GET之前。

需要CORS飞行前请求(OPTIONS调用)的内容类型是任何内容类型,除了以下内容:

应用程序/ x-www-form-urlencoded 多部分/格式 文本/平原

除了上面列出的内容类型外,任何其他内容类型都将触发飞行前请求。

对于header,除了以下以外的任何Request header都会触发一个pre-flight Request:

接受 接收语言 内容语言 内容类型 DPR 保存数据 Viewport-Width 宽度

任何其他请求头将触发预飞行请求。

因此,您可以添加一个自定义报头,如:x-Trigger: CORS,它应该触发飞行前请求并点击OPTIONS块。

参见MDN Web API参考- CORS预飞请求

我们可以避免CORS,而是将请求转发到另一个服务器:

// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'

// code:
console.log("starting server...");

var express = require('express');
var app = express();
var request = require('request');

// serve static files
app.use(express.static(public_folder));

// if not found, serve from another server
app.use(function(req, res) {
    var url = apiServerHost + req.url;
    req.pipe(request(url)).pipe(res);
});

app.listen(80, function(){
    console.log("server ready");
});

前段时间,我遇到了这个问题,所以我这样做是为了在我的nodejs应用程序中允许CORS:

首先你需要使用以下命令安装cors:

npm install cors --save

现在将以下代码添加到应用程序的启动文件中,如(app.js或server.js)

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);