如何允许CORS?

时间:2011-08-15 16:53:24

标签: node.js express coffeescript cors

我正在尝试在使用Express.js Web框架的Node.js应用程序中支持CORS。我已阅读a Google group discussion有关如何处理此问题的内容,并阅读了一些有关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)没有发送初始OPTIONS请求。当我刚刚更新资源块时,我需要将跨源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块中设置标题?

37 个答案:

答案 0 :(得分:625)

我发现最简单的方法是使用node.js包cors。最简单的用法是:

var cors = require('cors')

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

当然,有很多方法可以根据您的需要配置行为;上面链接的页面显示了许多示例。

答案 1 :(得分:425)

尝试将控制权传递给下一个匹配的路线。如果Express首先匹配app.get路由,那么它将不会继续进入选项路由,除非你这样做(注意使用下一个)

app.get('somethingelse', function(req, res, next) {
    //..set headers etc.

    next();
});

在组织CORS的方面,我把它放在一个适合我的中间件中:

//CORS middleware
var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'example.com');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

    next();
}

//...
app.configure(function() {
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'cool beans' }));
    app.use(express.methodOverride());
    app.use(allowCrossDomain);
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

答案 2 :(得分:140)

要回答您的主要问题,如果POST或GET中包含任何非简单内容或标题,则CORS规范仅要求OPTIONS调用在POST或GET之前。

内容 - 需要CORS转航前请求的类型(OPTIONS调用)是除以下之外的任何Content-Type

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain
  4. 除上述内容之外的任何其他内容类型都会触发转机前请求。

    对于标题,除以下之外的任何请求标题都会触发飞行前请求:

    1. Accept
    2. Accept-Language
    3. Content-Language
    4. Content-Type
    5. DPR
    6. Save-Data
    7. Viewport-Width
    8. Width
    9. 任何其他请求标头都会触发转机前请求。

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

      请参阅MDN Web API Reference - CORS Preflighted requests

答案 3 :(得分:110)

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

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示例相似

答案 4 :(得分:77)

DO

npm install cors --save

只需将这些行添加到您的请求所在的主文件中(在任何路由之前保留它)。

const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());

答案 5 :(得分:49)

我已经制作了一个更完整的中间件,适合快递或连接。它支持OPTIONS预检检查请求。请注意,它允许CORS访问任何内容,如果您想限制访问,可能需要进行一些检查。

app.use(function(req, res, next) {
    var oneof = false;
    if(req.headers.origin) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        oneof = true;
    }
    if(req.headers['access-control-request-method']) {
        res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
        oneof = true;
    }
    if(req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
        oneof = true;
    }
    if(oneof) {
        res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
    }

    // intercept OPTIONS method
    if (oneof && req.method == 'OPTIONS') {
        res.send(200);
    }
    else {
        next();
    }
});

答案 6 :(得分:36)

安装expressjs的cors模块。您可以按照以下步骤操作>

安装

npm install cors

简单用法(启用所有CORS请求)

var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());

有关详情,请转至https://github.com/expressjs/cors

答案 7 :(得分:31)

做这样的事情:

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

答案 8 :(得分:19)

首先只需在项目中安装cors即可。 将终端(命令提示符)和cd带到项目目录并运行以下命令:

npm install cors --save

然后获取server.js文件并更改代码以在其中添加以下内容:

var cors = require('cors');


var app = express();

app.use(cors());

app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   next();
});

这对我有用..

答案 9 :(得分:19)

使用express + node + ionic在不同端口运行完成测试。

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();
});

答案 10 :(得分:10)

这适合我,因为它在路线中很容易实现,我使用meanjs及其工作正常,safari,chrome等。

app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){ 
        res.header('Access-Control-Allow-Origin', '*'); 
        res.header('Access-Control-Allow-Methods', 'GET, POST');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        return res.send(200);

    });

答案 11 :(得分:10)

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

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

npm install cors --save

现在将以下代码添加到您的应用启动文件中,如(app.js or 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);

答案 12 :(得分:7)

如果您想使控制器具体,您可以使用:

res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');

请注意,这也允许使用iframe。

答案 13 :(得分:4)

可以参考以下代码。来源:Academind/node-restful-api

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

//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
    res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
    );
    if(req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
        return res.status(200).json({});
    }
    next(); //so that other routes can take over
})

答案 14 :(得分:3)

除了其他人所说的内容之外,请不要忘记,除非使用nodemon,否则您需要重启节点服务器才能使更改生效!

我个人一直习惯于刷新我的浏览器,忘记它是服务器端代码。

答案 15 :(得分:3)

使用Express Middleware非常适合我。如果您已经在使用Express,则只需添加以下中间件规则。它应该开始工作。

app.all("/api/*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
  return next();
});

app.all("/api/*", function(req, res, next) {
  if (req.method.toLowerCase() !== "options") {
    return next();
  }
  return res.send(204);
});

Reference

答案 16 :(得分:3)

我使用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', ...)也会有用......

答案 17 :(得分:2)

我发现使用npm请求包(https://www.npmjs.com/package/request)非常容易

然后我根据这篇文章http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/

建立了我的解决方案
'use strict'

const express = require('express');
const request = require('request');

let proxyConfig = {
    url : {
        base: 'http://servertoreach.com?id=',
    }
}

/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);


/* methods forwarded to the servertoreach proxy  */
server.use('/somethingElse', function(req, res)
{
    let url = proxyConfig.url.base + req.query.id;
    req.pipe(request(url)).pipe(res);
});


/* start the server */
server.listen(server.get('port'), function() {
    console.log('express server with a proxy listening on port ' + server.get('port'));
});

答案 18 :(得分:2)

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

答案 19 :(得分:2)

以下为我工作,希望它能对某人有所帮助!

1 extensionsUninstalledSoFar, IInstalledExtensionList modifiedInstalledExtensionsList, AsyncOperation asyncOp, IProgress

获得了https://expressjs.com/en/resources/middleware/cors.html#configuring-cors的引用

答案 20 :(得分:2)

在我的index.js中,我添加了:

app.use((req, res, next) => {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
   next();
}) 

答案 21 :(得分:2)

最简单的答案是只使用cors package

const cors = require('cors');

const app = require('express')();
app.use(cors());

这将全面启用CORS。如果您想学习如何enable CORS without outside modules,那么您真正需要的只是一些Express middleware来设置'Access-Control-Allow-Origin' header。这是允许从浏览器到服务器的跨请求域的最低要求。

app.options('*', (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  res.send('ok');
});

app.use((req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
});

答案 22 :(得分:1)

我在网络应用程序中使用了以下步骤,并取得了成功:

将cors包添加到express:

npm install cors --save

在bodyParser配置之后添加以下行。我在bodyParser之前添加了一些麻烦:

 // enable cors to the server
const corsOpt = {
    origin: process.env.CORS_ALLOW_ORIGIN || '*', // this work well to configure origin url in the server
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
    allowedHeaders: ['Content-Type', 'Authorization'] // allow json and token in the headers
};
app.use(cors(corsOpt)); // cors for all the routes of the application
app.options('*', cors(corsOpt)); // automatic cors gen for HTTP verbs in all routes, This can be redundant but I kept to be sure that will always work.

答案 23 :(得分:1)

我们可以避免使用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");
});

答案 24 :(得分:1)

简单很难:

react-final-form

答案 25 :(得分:0)

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,
  })
);

答案 26 :(得分:0)

如果你想让 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(),我不熟悉。

答案 27 :(得分:0)

使用CORS软件包。并输入以下参数:

cors({credentials: true, origin: true, exposedHeaders: '*'})

答案 28 :(得分:0)

在您的主要js文件中尝试以下操作:

app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
  "Access-Control-Allow-Headers",
  "Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method"
);
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
res.header("Allow", "GET, POST, OPTIONS, PUT, DELETE");
next();
});

这应该可以解决您的问题

答案 29 :(得分:0)

/ *首先,这可能是像我这样的初级开发人员之间的问题:请确保在您的 fetch <中使用“ lambda” >>>>“`”而不是“'” / strong>方法! * /

```const response = await fetch(https://api....);

/ plus,强烈建议以下文章:https://developer.edamam.com/api/faq /

答案 30 :(得分:0)

您可以使用Express中间件,阻止您的域和方法。

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", process.env.DOMAIN); // update to match the domain you will make the request from
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});

答案 31 :(得分:0)

如果我是你@OP,我会更改我的编程范例。

假设由于要向localhost或类似的请求而使这些CORS被阻止。

最终,如果您要部署到Google Cloud PlatformHeroku或这样的生产视蛋白,则不必担心诸如允许原产地之类的CORS或生产中的任何东西。

因此,在测试服务器时,只需使用postman,在部署服务器然后在客户端上工作之后,您就不会受到CORS的阻止。

答案 32 :(得分:0)

const express = require("express");
const router = express.Router();
const app = express();
const cors = require("cors"); 



const options = {
  origin: true,
  "Access-Control-Allow-Credentials": true,

  "Access-Control-Allow-Origin": true,
  "Access-Control-Allow-Headers": true,
  "Access-Control-Expose-Headers": true
};


app.use(cors(options));
router.get("/", cors(options), (req, res) => {
  res.render("index", { title: "Express" });
});

module.exports = router;

对于GOOGLE CHROME,您需要添加“ Allow-Control-Allow-Origin”扩展名

Access-Control-Allow-Origin(Response标头)标头指示是否可以通过返回Origin请求标头的值来共享资源。 Access-Control-Allow-Origin标头打开了跨域访问的门

Access-Control-Allow-Credentials(响应头):true用于指示允许客户端使用凭据。默认情况下,客户端脚本无法读取对凭证请求的响应。这样您就可以访问响应。另外,默认情况下,CORS在跨域请求中不包含cookie,这可能导致一类称为跨站点请求伪造或CSRF的漏洞。 为了减少CORS中CSRF漏洞的可能性,CORS要求服务器和客户端都承认可以在请求中包含cookie。

Access-Control-Expose-Headers(响应头)指示可以安全公开的头。可以读取响应中的标头的列表。默认情况下,仅公开6个简单响应头: 缓存控制,内容语言,内容类型,过期,最后修改,编译指示

Access-Control-Request-Headers(请求标头)指示在实际请求期间可以使用哪些HTTP标头。

origin = true(请求标头)反映了请求的来源。如果为假,Cors将被禁用。

答案 33 :(得分:0)

最简单的方法是使用以下命令在您的项目中安装cors模块:

npm i --save cors

然后在服务器文件中使用以下命令将其导入:

import cors from 'cors';

然后简单地将其用作这样的中间件:

app.use(cors());

希望这会有所帮助!

答案 34 :(得分:0)

使用不带Express / External库的nodejs,我在server.js文件中使用了以下方法。这里的关键部分是从请求标头获取原点,然后在服务器响应中允许它,这时我们可以设置将被返回的标头,包括找到匹配项时允许的原点。

    **const origin = req.headers.origin;**

      let decoder = new StringDecoder('utf-8');
      let buffer = '';
      req.on('data', function (data) {
        buffer += decoder.write(data);
      });
      req.on('end', function () {
        buffer += decoder.end();

        let chosenHandler = typeof (server.router[trimmedPath]) !== 'undefined' ? server.router[trimmedPath] : handlers.notFound;

const data = { ....data object vars}

// should be wrapped in try catch block
      chosenHandler(data, function (statusCode, payload, contentType) {
        server.processHandlerResponse(res, method, trimmedPath, statusCode, payload, contentType, **origin**);


server.processHandlerResponse = function (res, method, trimmedPath, statusCode, payload, contentType, origin) {
  contentType = typeof (contentType) == 'string' ? contentType : 'json';

  statusCode = typeof (statusCode) == 'number' ? statusCode : 200;

  let payloadString = '';
  if (contentType == 'json') {
    res.setHeader('Content-Type', 'application/json');

    const allowedOrigins = ['https://www.domain1.com', 'https://someotherdomain','https://yetanotherdomain',
    ...// as many as you need
  ];
    **if (allowedOrigins.indexOf(origin) > -1) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }**
    payload = typeof (payload) == 'object' ? payload : {};
    payloadString = JSON.stringify(payload);
  }

... //  if (other content type) ...rinse and repeat..

答案 35 :(得分:0)

下面的代码可以使用,但是首先通过以下方式安装cors:

npm install --save cors

然后:

module.exports = function(app) { 
var express = require("express");
var cors = require('cors');
var router = express.Router();
app.use(cors());

app.post("/movies",cors(), function(req, res) { 
res.send("test");
});

答案 36 :(得分:0)

在打字稿中,如果要使用node.js软件包cors

/**
* app.ts
* If you use the cors library
*/

import * as express from "express";
[...]
import * as cors from 'cors';

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       const corsOptions: cors.CorsOptions = {
           origin: 'http://example.com',
           optionsSuccessStatus: 200
       };
       this.express.use(cors(corsOptions));
   }
}

export default new App().express;

如果您不想使用第三方库进行cors错误处理,则需要更改handleCORSErrors()方法。

/**
* app.ts
* If you do not use the cors library
*/

import * as express from "express";
[...]

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       this.express.use((req, res, next) => {
           res.header("Access-Control-Allow-Origin", "*");
           res.header(
               "Access-Control-ALlow-Headers",
               "Origin, X-Requested-With, Content-Type, Accept, Authorization"
           );
           if (req.method === "OPTIONS") {
               res.header(
                   "Access-Control-Allow-Methods",
                   "PUT, POST, PATCH, GET, DELETE"
               );
               return res.status(200).json({});
           } 
           next(); // send the request to the next middleware
       });
    }
}

export default new App().express;

用于使用app.ts文件

/**
* server.ts
*/
import * as http from "http";
import app from "./app";

const server: http.Server = http.createServer(app);

const PORT: any = process.env.PORT || 3000;
server.listen(PORT);