如何在Express中启用CORS?

52

简而言之,我正在使用类似于DICOM文件的查看器API,称为Cornerstone。为此,我连接到dc4chee的WADO服务获取DICOM文件,dcm4chee运行在8080端口上,我的Node应用程序使用3000端口,因此我正在尝试显示浏览器的DICOM文件。

https://www.npmjs.com/package/cornerstone-wado-image-loader

这是浏览器显示的错误。

XMLHttpRequest can not load http: // localhost: 8080 / wado? RequestType = WADO & studyUID = 1.2.840.113704.1.111.5 ... 26513.429 & contentType = application% 2Fdicom & transferSyntax = 1.2.840.10008.1.2. In 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http: // localhost: 3000' is therefore not allowed access.

在文档中指定:

请注意,网页服务器必须支持跨源资源共享,否则图像将无法加载。如果您无法在加载DICOM P10实例的Web服务器上启用CORS,则可以使用反向代理。这是一个基于http-proxy的简单Node.js示例代码,可添加CORS标头,您可能会发现它很有用。

并展示了这个例子的代码,但我正在使用express,这段代码不起作用。

Var http = require ('http'),
    HttpProxy = require ('http-proxy');

Var proxy = httpProxy.createProxyServer ({target: 'http: // localhost: 8042'}) .listen (8000);

Proxy.on ('proxyRes', function (proxyReq, req, res, options) {
  // add the CORS header to the response
  Res.setHeader ('Access-Control-Allow-Origin', '*');
});

Proxy.on ('error', function (e) {
  // suppress errors
});

这里也要使用npm的cors代码

Var express = require ('express')
Var cors = require ('cors')
Var app = express ()
 
App.get ('/ products /: id', cors (), function (req, res, next) {
  Res.json ({msg: 'This is CORS-enabled for a Single Route'))
})
 
App.listen (80, function () {
  Console.log ('CORS-enabled web server listening on port 80')
})

但是这样我只能在端口3000上启用CORS,而不是8080。我需要以模式激活或添加“Access-Control-Allow-Origin”到响应标头而不是请求标头中。

我该如何在运行NODEjs的dcm4chee上添加端口8080的CORS呢?

更新!

服务器以以下方式响应:

RESPONDE HEADER

Content-Type:application/dicom
Date:Sat, 01 Apr 2017 01:15:38 GMT
Expires:0
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
X-Powered-By:Servlet 2.4; JBoss-4.2.3.GA (build: SVNTag=JBoss_4_2_3_GA 
date=200807181439)/JBossWeb-2.0

请求头

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:es-ES,es;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:localhost:8080
Origin:http: //localhost:3000
Referer:http: //localhost:3000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like 
Gecko) Chrome/55.0.2883.87 Safari/537.36

如何在响应头中启用跨源资源共享(CORS)?


4
这段代码是否真正启动了服务器?你有几个语法错误... Var不能大写,而且你正在大写变量名(变量名区分大小写),比如使用App,但你却定义它为app - AJ Funk
可能是重复的问题,参考No 'Access-Control-Allow-Origin' - Node / Apache Port Issue - Patrick Roberts
1
可能是如何允许CORS?的重复问题。 - zguesmi
请查看 https://dev59.com/4aTja4cB1Zd3GeqPId3H#46024491 - Tal
观察 App.get('/products/:id', cors(), function(req, res, next) { res.json({msg: 'This is CORS-enabled for a Single Route')) }) - Resres 不是同一个变量。 - John
11个回答

80

npm install cors --save

只需在发送请求的主文件中添加这些行。

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

1
这是答案 -- 预检请求在HTTP中使用OPTIONS动词,而.options()处理这些动词。 - O. Jones
1
@O.Jones 当使用 app.use(cors()); 将 cors 作为全局中间件时,您不需要再为其分配 OPTIONS 请求。请参见此处的说明:http://expressjs.com/en/resources/middleware/cors.html#enabling-cors-pre-flight - Basti

12

将CORS(跨源资源共享)添加到您的Node.js、Express应用程序中非常容易...

首先,您需要通过以下命令安装npm软件包cors

npm install cors -S

如果你需要全局使用它,只需添加-g标志...

然后在你的Express应用程序中执行以下操作:

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

这里是他们文档中有关 CORS 的其他示例:

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

app.use(cors())

app.get('/products/:id', function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

异步配置CORS:

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

var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
  var corsOptions;
  if (whitelist.indexOf(req.header('Origin')) !== -1) {
    corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
  }else{
    corsOptions = { origin: false } // disable CORS for this request
  }
  callback(null, corsOptions) // callback expects two parameters: error and options
}

app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

1
我来晚了,最新的Express Router是一个单独的模块,我们必须依赖它。那么,如何在异步路由中应用CORS?例如:router.get('/', cors(corsOptions), async (req, res) => res.json('test') - Mithun Shreevatsa
@MithunShreevatsa Express 永远不使用任何中间件或路由处理程序的返回值,因此它们是否异步并不重要。 - Phil

10

要启用跨域资源共享,您可以这样做:

var cors = require('cors');
app.use(cors());
// to change your ports for different cors stuff:
app.set('port', process.env.PORT || 3000);
app.listen(app.get('port'), function() { 
  console.log('we are listening on: ', 
  app.get('port'))
});

请记住,cors 是中间件,因此您需要在其之前使用 app.use,以便您的传入请求在到达路由之前经过 cors 处理。
您可以根据所需使用的端口更改端口。我相信您也可以用 && 替换 || 以便在多个端口上监听并设置 cors。
在原始节点中,我认为您必须使用 writeHead,但我不确定原始节点实现情况。

我的问题来自于端口8080,因为我在端口8080上添加了Access-Control-Allow-Origin,这是dcm4chee服务工作的地方,它为我提供DICOM文件。我的应用程序在端口3000上运行,并已经在端口3000上启用了CORS,但是当我在提供DICOM图像的服务所在的端口8080上启用CORS时,这就是我的问题。 - M. Node

9
浏览器显示的错误意味着,服务器 localhost:8080 拒绝了来自 localhost:3000 的请求,看起来跨域资源共享设置在服务器 localhost:8080 上没有设置好。
响应头应该有以下内容:
Access-Control-Allow-Headers:Content-Type,Content-Length, Authorization, Accept,X-Requested-With
Access-Control-Allow-Methods:PUT,POST,GET,DELETE,OPTIONS
Access-Control-Allow-Origin:*

尝试在你的8080服务器中添加CORS头。
app.all('*', function (req, res) {
 res.header("Access-Control-Allow-Origin", "*");
 res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
 res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
 //...
});

我的问题是在端口8080上dcm4chee工作,我该如何添加呢?我的应用程序在端口3000上工作,我该如何配置它? - M. Node
1
只需在8080服务器上使用app.use(cors());即可。 - cxxsn
这是我不理解的地方,抱歉我的无知。由于我正在使用NODEJS并且我的应用程序在端口3000上,而DCM4CHEE在端口8080上,我无法将CORS从我的端口3000应用程序汇聚到DCM4CHEE所使用的8080端口。我该如何为端口3000应用程序配置用于DICOM提供程序DCM4CHEE的8080端口CORS?我不知道我是否解释清楚了,很抱歉=(我尝试在我的应用程序的app.js中使用app.use(cors({source:'localhost:8080';}));) - M. Node
似乎您可能错过了CORS的一些要点。如果您在端口3000上启用CORS,则意味着其他服务器上提供的页面可以请求localhost:3000,假设您在端口3000服务器上有一个restful api,如/getSomeInfo,然后在端口8888上启动一个新服务器,提供一些html文件,打开浏览器并访问localhost:8888/test.html,test.html可以请求localhost:3000/getSomeInfo - cxxsn
如果“仅在端口3000上激活CORS,而不是在端口8080上”,则在3000服务器上提供的页面无法请求8080服务器。实际上,应该是“仅在端口8080上激活CORS,而不是在端口3000上”。如果无法修改8080服务器,则可以设置一个中间代理服务器,例如localhost:8000,并设置此服务器允许CORS请求。然后,在浏览器中,来自localhost:3000的页面请求localhost:8000,localhost:8000请求localhost:8080,并将响应发送到localhost:3000。CORS请求阻止发生在浏览器中,而不是服务器中。 - cxxsn
显示剩余4条评论

7

在本地主机上使用CORS不起作用,直到我将请求URL添加http://

localhost:3001不起作用

http://localhost:3001很好地工作了

这是我的最终可行代码

Node端

var cors = require('cors')
const app = express();
app.use(cors()); // Make sure this line comes right after express()

前端方面

let response = await axios.post("http://localhost:3001/uploadFile", formData); 
// the http:// is required cors to work for localhost

4

这段代码帮助我解决了在express中出现的资源跨域问题。并且您可以轻松使用异步源配置的其他选项。

var cors = require('cors'); //import cors module

var whitelist = ['http://localhost:8000', 'http://localhost:8080']; //white list consumers
var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(null, false);
    }
  },
  methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
  optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
  credentials: true, //Credentials are cookies, authorization headers or TLS client certificates.
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'device-remember-token', 'Access-Control-Allow-Origin', 'Origin', 'Accept']
};

app.use(cors(corsOptions)); //adding cors middleware to the express with above configurations

它没起作用,原点未定义。 - undefined

3

首先要解决这个问题,你需要理解Access-Control-Allow-Origin是什么:这个头部的值将是你发送请求到服务器(例如express)的主机。

步骤1:在服务器端允许跨域资源共享(CORS),(你可以使用*代替http://localhost:3000来允许跨域请求)

var express = require("express");
var app = express();
 
 
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*"); // update to match the domain you will make the request from
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

步骤二:只需使用您的http客户端,我正在使用Axios:

var qs = require("querystring");
var axios = require("axios");
const sendEmail = (email, subject, template) => {

    var data = qs.stringify({
        email: email,
        subject: subject,
        template: template,
    });
    var config = {
        method: "post",
        url: "https://abc-domain.com/endpoint",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded",
        },
        data: data,
    };

    axios(config)
        .then(function(response) {
            console.log(JSON.stringify(response.data));
        })
        .catch(function(error) {
            console.log(error);
        });
};

module.exports = sendEmail;

0

我也遇到了这个问题。 为了解决它,我使用了CORS模块,并将其导入到我的路由中:

import cors from 'cors';
const router = new Router();
router.get('/posts', cors(), PostController.getAll);

0
//Définition des CORS Middleware 
app.use(function(req, res, next) {
    res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type, Accept,Authorization,Origin");
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
    res.setHeader("Access-Control-Allow-Credentials", true);
    next();
  });`enter code here`

0
在Node.js Express项目中启用cors,首先使用npm安装cors。
npm i cors
然后
import express from "express";
import cors from "cors";

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

然而,这将允许任何域名访问您的后端。如果您想限制对特定域名的访问,则可以在这里找到有关如何使用cors的详细答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接