否'Access-Control-Allow-Origin' - 节点/ Apache端口问题

时间:2013-08-19 09:22:51

标签: node.js angularjs rest express cors

我使用Node / Express创建了一个小API,并尝试使用Angularjs来提取数据,但是当我的html页面在localhost:8888上的apache下运行,而节点API在端口3000上侦听时,我得到了No'访问权限 - 控制允许来源。我尝试使用node-http-proxy和Vhosts Apache但没有取得多大成功,请参阅下面的完整错误和代码。

“XMLHttpRequest无法加载localhost:3000。请求的资源上没有'Access-Control-Allow-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 code
    angular.module('contractorsApp', [])
    .controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').success(function(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>

14 个答案:

答案 0 :(得分:545)

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

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

希望有所帮助!

答案 1 :(得分:81)

接受的答案很好,如果您喜欢更短的内容,可以使用名为 cors 的插件,可用于Express.js

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

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));

答案 2 :(得分:27)

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

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:)');
});

答案 3 :(得分:14)

top answer对我来说很好,除了我需要将多个域列入白名单。

此外,最佳答案还有一个事实,即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);
});

答案 4 :(得分:12)

答案代码仅允许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();
});

答案 5 :(得分:6)

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

npm i --save cors

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

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

它适用于我的2.8.4 cors版本。

答案 6 :(得分:5)

所有其他答案都不适合我。 (包括cors包,或者通过中间件设置headers)

对于 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"]
    }
});

答案 7 :(得分:4)

这对我有用。

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

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

您可以更改*以适合您的需求。希望这会有所帮助。

答案 8 :(得分:3)

嗨,这发生在前端和后端在不同端口上运行时。由于缺少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

答案 9 :(得分:2)

//Add following code in app.js of NODEJ Restful api to avoid "Access-Control-Allow-Origin" error in angular 6 or any other framework

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

答案 10 :(得分:1)

您可以使用“$ http.jsonp”

OR

以下是针对本地测试的chrome的解决方法

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

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

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

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

使用“--allow-file-access-from-files”

在MAC中打开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

答案 11 :(得分: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。您可能已经在/etc/nginx/nginx.conf nginx.conf 文件中定义了该指令,现在您需要在client_max_body_size上添加/编辑指令http的值或server

server {
    client_max_body_size 100M;
    ...
}

设置好所需的值后,保存更改并重新加载 Nginx service 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,e.g.%20a%20large%20media%20file)。

答案 12 :(得分:0)

/**
 * 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.

答案 13 :(得分:0)

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

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

app.use(cors())

用于设置具体的原点

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

know more