对于$ save方法,AngularJS $资源使HTTP OPTIONS请求代替HTTP POST

我正在编写一个简单的库应用程序,以便为使用AngularJS的大型项目做好准备。 在网上阅读了大量有关使用$resource与RESTful API进行交互的信息之后,我决定为实现它而提供一些节省时间和扩展的好处,而不是为每个请求使用$http 。 问题是,由于某种原因(我不是CORS的专家,请求正在跨域发送),当使用$save方法时,我的Node.js控制台显示:

 OPTIONS /books 200 1ms - 161b 

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

 GET /books 200 1ms - 228b 

我已经坚持了几个小时在这一点,试图在下面的变化,但它总是最终是一个OPTIONS请求,而不是POST(这是什么,它应该是根据Angular文档)为$save方法。

AngularJS Web App

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

尝试把这行在我的configurationfunctiondelete $httpProvider.defaults.headers.common["X-Requested-With"]; 但没有变化。

我不是Angular / Node的专家,但现在我正在考虑这是跨域的问题,就像我说的,我不是CORS的专家。

提前致谢。

我知道回答我自己的问题可能会有不好的口味,但是我发现这个问题在发布几天之后就已经解决了。

这一切都归结于浏览器如何pipe理CORS。 当在JavaScript中进行一个不是“简单”的跨域请求时(例如GET请求 – 这解释了为什么query()函数起作用),浏览器将自动向指定的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('*', function(req, res, 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('*', function(req, res) { res.send(200); }); 

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

我没有真正尝试这个,但是不能告诉资源如何处理$ save请求?

 $resource('http://mywebserver\\:1337/books/:bookId', { bookId: '@bookId' }, {save: {method: 'POST'}); 
Interesting Posts