本地 Nodejs 服务器不允许跨域请求

Posted

技术标签:

【中文标题】本地 Nodejs 服务器不允许跨域请求【英文标题】:Can't allow Cross-Origin Request in local Nodejs server 【发布时间】:2018-04-01 11:29:35 【问题描述】:

我在 nodejs 中创建了一个本地 REST API 服务器,它从本地 Mongodb 数据库中获取数据。我还创建了一个基本网页,它从本地服务器请求这些数据。现在,当我尝试从网页获取数据时,它给了我以下错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4000/todos. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

我在 *** 上搜索了一下,找到了 THIS 和 THIS 解决方案。我已经在我的主 app.js 文件中添加了建议的标题。但它仍然给出了同样的错误。

以下是我的服务器app.js 文件,我在其中添加了这些标头。

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');
var todos = require('./routes/todos');

// load mongoose package
var mongoose = require('mongoose');

// Use native Node promises
mongoose.Promise = global.Promise;

// connect to MongoDB
mongoose.connect('mongodb://localhost/todo-api')
.then(() =>  console.log('connection succesful'))
.catch((err) => console.error(err));

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded( extended: false ));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);
app.use('/todos', todos);

// 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();
);
 // catch 404 and forward to error handler
    app.use(function(req, res, next) 
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
);

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') 
  app.use(function(err, req, res, next) 
    res.status(err.status || 500);
    res.render('error', 
      message: err.message,
      error: err
    );
  );


// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) 
  res.status(err.status || 500);
  res.render('error', 
    message: err.message,
    error: 
  );
);

module.exports = app;

以下是网页的代码(Angularjs),我想从我的 API 中获取数据。

dbConnection.html

<html ng-app="demo">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"> </script>
<head>
    <title> dbConnection Demo</title>
</head>

<body ng-controller="db">
    <div ng-repeat="product in db.products">
        product._id </br>
    </div>
</body>

<script>
    var app = angular.module('demo', []);
    app.controller('db', ['$http', function($http)
        var store = this;
        store.products = [];

        $http(
            method: 'GET',
            url: 'http://localhost:4000/todos'
            ).then(function (success)
                store.products = success;
            ,function (error)

            );
    ]);
</script>
</html>

即使按照答案中的建议添加了标题,我也遇到了同样的错误。我在这里想念什么?我在这个领域完全是新手。谢谢!

【问题讨论】:

试试CORS middleware 链接中的documentation 彻底解释了这一点。 我尝试了第一个简单的用法,但仍然是同样的错误:( 【参考方案1】:

您的请求是否需要飞行前响应?如果是这样,它将尝试使用“OPTIONS”方法访问您的端点,除非您设置了一个,否则您将看到 cors 问题。

因此,如果您发现预检响应失败,您可以添加自定义选项路由,或者可能使用 npm cors 包 - https://www.npmjs.com/package/cors

npm install cors --save

在你的 app.js 中

var cors = require('cors')


app.options('*', cors()) // include before other routes 
app.use(cors())

【讨论】:

【参考方案2】:

我终于通过在我的路由中添加这些标题找到了解决方案,如下所示:

routes/todos.js

...
...
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,contenttype'); // If needed
res.setHeader('Access-Control-Allow-Credentials', true); // If needed

res.send('cors problem fixed:)');
);

【讨论】:

【参考方案3】:

请将标题代码移到var app = express(); 之后 这意味着您必须在定义路由器之前放置它们。

var app = express();
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();
);

// Router

【讨论】:

请看代码。我目前在我的app.js 中使用它。 我的意思是你必须把它放在路由器之前【参考方案4】:

您可能需要添加:

 res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

为什么?好吧,我想我有同样的问题,这为我解决了。

【讨论】:

我必须在删除以前的方法后添加这一行?

以上是关于本地 Nodejs 服务器不允许跨域请求的主要内容,如果未能解决你的问题,请参考以下文章

nodejs 代理 解决开发环境跨域问题

通过注解的方式允许跨域

nodejs做http请求转发,解决js跨域问题(二)

如何允许跨域

AngularJS和跨域请求被阻止[关闭]

nodejs——解决跨域问题