我正在编写一个简单的图书馆应用程序,为AngularJS准备一个更大的项目。在网上阅读了很多关于使用$资源与RESTful API进行交互的资料之后,我决定可能会为实现它而提供一些节省时间和扩展的好处,而不是为每个请求使用$ http。问题是,由于某些原因(我不是CORS的专家,并且请求正在发送跨域)当使用$ save方法时,我的Node.js控制台显示:
OPTIONS /books 200 1ms - 161b
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); });
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。