本地 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 服务器不允许跨域请求的主要内容,如果未能解决你的问题,请参考以下文章