AngularJS $资源使得HTTP OPTIONS请求而不是HTTP POST为$保存方法 [英] AngularJS $resource makes HTTP OPTIONS request instead of HTTP POST for $save method
问题描述
我在写一个简单的库应用程序来准备与AngularJS一个大项目的过程。在网上读了很多关于使用 $资源
与一个RESTful API进行互动后,我决定,这可能会提供一些节省时间和缩放利益来实现它,而不是使用 $ HTTP
为每个请求。现在的问题是,由于某种原因(我对CORS没有专家和请求发送跨域)使用 $保存
方法我Node.js的控制台显示了当
I'm in the process of writing a simple library application to get ready for a larger project with AngularJS. After reading a lot online about using $resource
to interact with a RESTful API, I decided that it would probably offer some time-saving and scaling benefits to implement it instead of using $http
for each request. The problem is that for some reason (I'm no expert on CORS and the request is being sent cross-domain) when using the $save
method my Node.js console shows:
OPTIONS /books 200 1ms - 161b
使用查询()
方法工作正常 - 节点控制台显示:
Using the query()
method works fine - the Node console shows:
GET /books 200 1ms - 228b
我一直停留几个小时在这一点,在下面试图变化,但它总是最终被一个OPTIONS请求,而不是在POST(这是它应根据角文档是什么)的 $保存
方法。
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();
};
}]);
与前preSS REST API
Node.js加载
app.js
Node.js with Express REST API
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'));
});
./路线/ books.js
...
exports.add = function(req, res) {
console.log("POST request received...");
console.log(req.body.isbn);
};
试图把此行中我的配置功能删除$ httpProvider.defaults.headers.common [X-要求,以];
,但没有改变。
我不是角/节点亲,但现在我认为它的东西,用它做是跨域,就像我说的,我对CORS没有专家。
I'm no Angular/Node pro but right now I'm thinking that it's something to do with it being cross domain and, like I said, I'm no expert on CORS.
先谢谢了。
推荐答案
我知道这可能是不好的味道回答我的问题,但我张贴这几天后想通了这个问题。
I know it may be in bad taste to answer my own question but I figured out the problem a few days after posting this.
这一切都归结到浏览器如何管理CORS。当使得JavaScript的跨域请求不简单(即GET请求 - 这也解释了为什么查询()
函数的工作),浏览器会自动进行一个HTTP OPTIONS请求到指定的URL / URI,称为pre-飞行请求或承诺。只要远程数据源返回200 HTTP状态code和相关细节什么它会在响应头接受,那么浏览器就会继续与原来的JavaScript调用。
It all comes down to how browsers manage CORS. When making a cross-domain request in JavaScript that is not "simple" (i.e. a GET request - which explains why the query()
function worked), the browser will automatically make a HTTP OPTIONS request to the specified URL/URI, called a "pre-flight" request or "promise". As long as the remote source returns a HTTP status code of 200 and relevant details about what it will accept in the response headers, then the browser will go ahead with the original JavaScript call.
下面是一个简短的jQuery的例子:
Here's a brief jQuery example:
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.
}
我所要做的就是添加什么样的服务器将在响应头接受详细信息:
All I had to do was add the details of what the server will accept in the response headers:
// 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();
});
,然后将前preSS路由之前的这几行简单地返回一个HTTP 200状态code,每OPTIONS请求:
And then insert these few lines before the Express routing to simply return a HTTP 200 status code for every OPTIONS request:
// fulfils pre-flight/promise request
app.options('*', function(req, res) {
res.send(200);
});
希望这将有助于任何人谁从同一个问题这个页面的痛苦失蹄。
Hopefully this will help anyone who stumbles on this page suffering from the same problem.
这篇关于AngularJS $资源使得HTTP OPTIONS请求而不是HTTP POST为$保存方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!