简体   繁体   English

不能在本地Nodejs服务器中允许跨源请求

[英]Can't allow Cross-Origin Request in local Nodejs server

I've created a local REST API server in nodejs, which is fetching data from local Mongodb database. 我在nodejs中创建了一个本地REST API服务器,它从本地Mongodb数据库中获取数据。 I've also created a basic web page, which request this data from the server locally. 我还创建了一个基本网页,它从本地服务器请求这些数据。 Now, when I try to get data from web page, it gives me following error: 现在,当我尝试从网页上获取数据时,它会出现以下错误:

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).

I've searched about on stackoverflow, and found THIS and THIS solutions. 我搜索了stackoverflow,发现了这个这个解决方案。 I've added the suggested headers in my main app.js file. 我在主app.js文件中添加了建议的标题。 But still it gives the same error. 但它仍然会给出同样的错误。

Following is my servers app.js file, where I've added these headers. 以下是我的服务器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;

And following is the code(Angularjs) of web page, from where I want to get data from my API. 以下是网页的代码(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>

Even after I've added headers as suggested in the answers, I'm getting the same error. 即使我在答案中建议添加标题后,我也会遇到同样的错误。 What am I missing here? 我在这里错过了什么? I'm completely newbie in this field. 我是这个领域的新手。 Thanks! 谢谢!

Does your request require a pre-flight response? 您的请求是否需要飞行前回复? If it does, it will be trying to hit your endpoint with method 'OPTIONS' and unless you have set one up, you will see the cors issue. 如果是这样,它将尝试使用“OPTIONS”方法命中你的终点,除非你设置了一个,否则你会看到cors问题。

So if you find that the preflight response is failing, you can either add a custom options route, or potential use the npm cors package - https://www.npmjs.com/package/cors 因此,如果您发现预检响应失败,您可以添加自定义选项路由,也可以使用npm cors包 - https://www.npmjs.com/package/cors

npm install cors --save

In your app.js 在你的app.js中

var cors = require('cors')


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

I finally figured out the solution by adding those headers in my routes as following: 我最终通过在我的路由中添加这些标题来找出解决方案,如下所示:

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

You might have to add: 您可能需要添加:

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

Why? 为什么? Well I think I had the same problem and this solved it for me. 好吧,我想我有同样的问题,这解决了我。

Please move the header code after var app = express(); 请在var app = express();之后移动标题代码var app = express(); That mean you must place them before define router. 这意味着你必须在定义路由器之前放置它们。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM