我试图在使用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块设置标题?


当前回答

express + node +离子在不同端口运行时进行测试。

Localhost: 8100

Localhost: 5000

// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests

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

其他回答

如果您的快速服务器启用了授权,您可以像这样实现

const express = require('express');
const app=express();
const cors=require("cors");
app.use(cors({
   credentials: true, // for authorization
}));
...

这与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。

cors包是在express.js中解决cors策略问题的推荐方法,但你也需要确保在app.options中启用它,如下所示:

const cors = require('cors');

// enable cors
app.use(
  cors({
    origin: true,
    optionsSuccessStatus: 200,
    credentials: true,
  })
);
app.options(
  '*',
  cors({
    origin: true,
    optionsSuccessStatus: 200,
    credentials: true,
  })
);

我对Express 4.2.0的最简单的解决方案(编辑:在4.3.0中似乎不起作用)是:

function supportCrossOriginScript(req, res, next) {
    res.status(200);
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type");

    // res.header("Access-Control-Allow-Headers", "Origin");
    // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // res.header("Access-Control-Allow-Methods","POST, OPTIONS");
    // res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
    // res.header("Access-Control-Max-Age","1728000");
    next();
}

// Support CORS
app.options('/result', supportCrossOriginScript);

app.post('/result', supportCrossOriginScript, function(req, res) {
    res.send('received');
    // do stuff with req
});

我想做app.all('/result',…)也可以…

如果你想让CORS在没有CORS NPM包的情况下工作(纯粹为了学习的乐趣!),你完全可以自己处理OPTIONS调用。以下是对我有效的方法:

app.options('*', (req, res) => {
    res.writeHead(200, '', {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'OPTIONS',
    }).end();
});

很简单,对吧?注意使用res.writeHead()而不是res.header(),这一点我不熟悉。