node.js – AngularJS $资源使用HTTP OPTIONS请求而不是HTTP POST用于$save方法

我正在编写一个简单的图书馆应用程序,为AngularJS准备一个更大的项目。在网上阅读了很多关于使用$资源与RESTful API进行交互的资料之后,我决定可能会为实现它而提供一些节省时间和扩展的好处,而不是为每个请求使用$ http。问题是,由于某些原因(我不是CORS的专家,并且请求正在发送跨域)当使用$ save方法时,我的Node.js控制台显示

OPTIONS /books 200 1ms - 161b

使用query()方法工作正常 – Node控制台显示

GET /books 200 1ms - 228b

在这一点上,我已经停了几个小时,尝试下面的变体,但是它总是以$ save方式而不是POST(根据Angular文档应该是一个OPTIONS)请求。

AngularJS Web应用程序

app.js

var libraryApp = angular.module('libraryApp',['ngResource','ngRoute','libraryControllers']);

libraryApp.factory('$book',['$resource',function ($resource) {

    return $resource('http://mywebserver\\:1337/books/:bookId',{ bookId: '@bookId' });
}]);

controllers.js

var libraryControllers = angular.module('libraryControllers',[]);

libraryControllers.controller('BookCtrl',['$scope','$book',function($scope,$book) {

    ...

    $scope.addBook = function () {
        var b = new $book;
        b.isbn = "TEST";
        b.description = "TEST";
        b.price = 9.99;
        b.$save();
    };
}]);

具有Express REST API的Node.js

app.js

var express = require('express'),books = require('./routes/books'),http = require('http'),path = require('path');

var app = express();

...

// enable cross-domain scripting
app.all('*',function(req,res,next) {
    res.header("Access-Control-Allow-Origin",req.headers.origin);
    res.header("Access-Control-Allow-Headers","X-Requested-With");
    next();
});

// routing
app.get('/books',books.getAll);
app.get('/books/:isbn',books.get);
// This is what I want to fire with the $save method
app.post('/books',books.add);

http.createServer(app).listen(app.get('port'),function(){
    console.log('Express server listening on port ' + app.get('port'));
});

./routes/books.js

...

exports.add = function(req,res) {

    console.log("POST request received...");
    console.log(req.body.isbn);
};

尝试将此行放在我的配置功能删除$ httpProvider.defaults.headers.common [“X-Requested-With”];但没有变化。

我不是Angular / Node pro,但现在我认为这是与跨域有关,像我说的,我不是CORS的专家。

提前致谢。

解决方法

我知道回答我自己的问题可能是不好的味道,但我发布了这几天后才发现了这个问题。

这一切都归功于浏览器如何管理CORS。当以不是“简单”的JavaScript进行跨域请求(即GET请求 – 这就是为什么查询()函数工作的原因)时,浏览器将自动对指定的URL / URI进行HTTP OPTIONS请求,称为“飞行前”请求或“承诺”。只要远程源程序返回HTTP状态代码为200,以及有关响应标头中将接受的相关详细信息,则浏览器将继续执行原始JavaScript调用

这是一个简单的jQuery示例:

function makeRequest() {
    // browser makes HTTP OPTIONS request to www.myotherwebsite.com/api/test
    // and if it receives a HTTP status code of 200 and relevant details about
    // what it will accept in HTTP headers,then it will make this POST request...
    $.post( "www.myotherwebsite.com/api/test",function(data) {
        alert(data);
    });
    // ...if not then it won't - it's that simple.
}

我只需要添加服务器将在响应标头中接受的细节:

// apply this rule to all requests accessing any URL/URI
app.all('*',next) {
    // add details of what is allowed in HTTP request headers to the response headers
    res.header('Access-Control-Allow-Origin',req.headers.origin);
    res.header('Access-Control-Allow-Methods','POST,GET,PUT,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Credentials',false);
    res.header('Access-Control-Max-Age','86400');
    res.header('Access-Control-Allow-Headers','X-Requested-With,X-HTTP-Method-Override,Content-Type,Accept');
    // the next() function continues execution and will move onto the requested URL/URI
    next();
});

然后在Express路由之前插入几行,以便为每个OPTIONS请求简单地返回HTTP 200状态代码

// fulfils pre-flight/promise request
app.options('*',res) {
    res.send(200);
});

希望这将帮助任何人绊倒在这页面上遇到同样的问题。

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...