322

我已经使用 Node/Express 创建了一个小型 API,并尝试使用 Angularjs 提取数据,但是由于我的 html 页面在 localhost:8888 上的 apache 下运行并且节点 API 在端口 3000 上侦听,所以我得到了 No 'Access-Control-允许来源'。我尝试使用 node-http-proxy和 Vhosts Apache 但没有太多成功,请参阅下面的完整错误和代码。

XMLHttpRequest 无法加载 localhost:3000。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'localhost:8888'。”

// Api Using Node/Express    
var express = require('express');
var app = express();
var contractors = [
    {   
     "id": "1", 
        "name": "Joe Blogg",
        "Weeks": 3,
        "Photo": "1.png"
    }
];

app.use(express.bodyParser());

app.get('/', function(req, res) {
  res.json(contractors);
});
app.listen(process.env.PORT || 3000);
console.log('Server is running on Port 3000')

角码

angular.module('contractorsApp', [])
.controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').then(function(response) {
       var data = response.data;
       $scope.contractors = data;
   })

HTML

<body ng-app="contractorsApp">
    <div ng-controller="ContractorsCtrl"> 
        <ul>
            <li ng-repeat="person in contractors">{{person.name}}</li>
        </ul>
    </div>
</body>
4

15 回答 15

761

尝试将以下中间件添加到您的 NodeJS/Express 应用程序(为了您的方便,我添加了一些注释):

// Add headers before the routes are defined
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // 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');

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

希望有帮助!

于 2013-08-19T10:23:25.687 回答
116

接受的答案很好,如果你喜欢更短的东西,你可以使用一个名为cors的插件,可用于 Express.js

对于这种特殊情况,使用起来很简单:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));
于 2015-12-18T00:11:24.220 回答
37

另一种方法是简单地将标题添加到您的路线中:

router.get('/', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // If needed
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // If needed
    res.setHeader('Access-Control-Allow-Credentials', true); // If needed

    res.send('cors problem fixed:)');
});
于 2016-11-26T16:14:06.177 回答
21

最佳答案对我来说很好,除了我需要将多个域列入白名单。

此外,最佳答案还受到OPTIONS中间件不处理请求并且您不会自动获取它的事实的影响。

我将列入白名单的域存储allowed_origins在 Express 配置中,并根据origin标头放置正确的域,因为Access-Control-Allow-Origin不允许指定多个域。

这就是我最终得到的结果:

var _ = require('underscore');

function allowCrossDomain(req, res, next) {
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');

  var origin = req.headers.origin;
  if (_.contains(app.get('allowed_origins'), origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

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

app.configure(function () {
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(allowCrossDomain);
});
于 2014-03-28T17:30:08.903 回答
14

答案代码只允许 localhost:8888。此代码不能部署到生产,或不同的服务器和端口名称。

要使其适用于所有来源,请改用:

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // 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');

    // 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();
});
于 2016-07-06T17:31:24.877 回答
14

在您的项目中安装 cors 依赖项:

npm i --save cors

将以下内容添加到您的服务器配置文件中:

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

它适用于我的 2.8.4 cors 版本。

于 2018-08-29T09:21:21.410 回答
14

嗨,当前端和后端在不同的端口上运行时会发生这种情况。由于缺少 CORS 标头,浏览器会阻止来自后端的响应。解决方案是在后端请求中添加 CORS 标头。最简单的方法是使用 cors npm 包。

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

这将在您的所有请求中启用 CORS 标头。有关更多信息,您可以参考 cors 文档

https://www.npmjs.com/package/cors

于 2019-08-18T14:01:06.540 回答
8

这对我有用。

app.get('/', function (req, res) {

    res.header("Access-Control-Allow-Origin", "*");
    res.send('hello world')
})

您可以更改 * 以满足您的需要。希望这能有所帮助。

于 2018-12-15T11:31:11.673 回答
6

所有其他答案都对我不起作用。(包括 cors 包,或通过中间件设置标头)

对于 socket.io 3^,这在没有任何额外包的情况下工作。

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

const server = require('http').createServer(app);
const io = require('socket.io')(server, {
    cors: {
        origin: "*",
        methods: ["GET", "POST"]
    }
});
于 2021-01-01T17:43:56.793 回答
4
app.all('*', function(req, res,next) {
    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

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


});
于 2015-12-21T12:51:03.503 回答
4

在 NODEJ Restful api 的 app.js 中添加以下代码,以避免在 Angular 6 或任何其他框架中出现“Access-Control-Allow-Origin”错误

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
}));
于 2018-05-22T14:55:20.433 回答
2

您可以使用“$http.jsonp”

或者

以下是用于本地测试的 chrome 解决方法

您需要使用以下命令打开您的 chrome。(按窗口+R)

Chrome.exe --allow-file-access-from-files

注意:您的 chrome 不得打开。当您运行此命令时,chrome 将自动打开。

如果您在命令提示符下输入此命令,请选择您的 chrome 安装目录,然后使用此命令。

下面的脚本代码用于在 MAC 中使用“--allow-file-access-from-files”打开 chrome

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"

第二种选择

您可以只使用open(1)添加标志: open -a 'Google Chrome' --args --allow-file-access-from-files

于 2013-08-19T09:30:31.020 回答
2

你可以使用 cors 包来处理它。

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

app.use(cors())

用于设置特定原点

app.use(cors({origin: 'http://localhost:8080'}));

了解更多

于 2021-08-08T05:02:37.163 回答
1

/**
 * Allow cross origin to access our /public directory from any site.
 * Make sure this header option is defined before defining of static path to /public directory
 */
expressApp.use('/public',function(req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // Set to true if you need the website to include cookies in the requests sent
    res.setHeader('Access-Control-Allow-Credentials', true);
    // Pass to next layer of middleware
    next();
});


/**
 * Server is about set up. Now track for css/js/images request from the 
 * browser directly. Send static resources from "./public" directory. 
 */
expressApp.use('/public', express.static(path.join(__dirname, 'public')));
If you want to set Access-Control-Allow-Origin to a specific static directory you can set the following.

于 2016-07-02T06:18:33.637 回答
1

除了所有列出的答案,我有同样的错误

我可以同时访问前端和后端,我已经添加了cors模块app.use(cors());不过,我一直在努力解决这个错误。

经过一番调试,我发现了问题。当我上传大小超过 1 MB 的媒体时,Nginx 服务器抛出了错误

<html>

<head>
    <title>413 Request Entity Too Large</title>
</head>

<body>
    <center>
        <h1>413 Request Entity Too Large</h1>
    </center>
    <hr>
    <center>nginx/1.18.0</center>
</body>

</html>

但是在前端的控制台中,我发现了错误

Access to XMLHttpRequest at 'https://api.yourbackend.com' from origin 'https://web.yourfromntend.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

所以这里很混乱。但是这个错误的路由原因是来自nginx配置。这只是因为指令client_max_body_size值默认设置为0。它决定了允许的 HTTP 请求大小是多少client_max_body_size。该指令可能已经在位于 的nginx.conf文件中定义,/etc/nginx/nginx.conf现在您需要client_max_body_sizehttp或处添加/编辑指令的值server

server {
    client_max_body_size 100M;
    ...
}

设置所需值后,保存更改并重新加载Nginxservice nginx reload

经过这些更改,它运行良好

参考https ://www.keycdn.com/support/413-request-entity-too-large#:~:text=%23,processed%20by%20the%20web%20server.&text=An%20example%20request% 2C%20that%20may,eg%20a%20large%20media%20file )。

于 2020-07-03T19:34:41.303 回答