cross domain CORS支持backbone.js
我正在尝试为我的骨干应用程序实施一个跨域设置。
我的服务器(express.js)允许跨域和凭证:
var allowCrossDomain = function(req, res, next) { var allowedHost = [ 'http://localhost:3001', 'http://localhost:7357' ]; if(allowedHost.indexOf(req.headers.origin) !== -1) { res.header('Access-Control-Allow-Credentials', true); res.header('Access-Control-Allow-Origin', req.headers.origin) res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'); next(); } else { res.send({auth: false}); } } app.configure(function(){ .... app.use(allowCrossDomain); .... });
我的客户端(backbone.js)被configuration为接受跨域:
define(["backbone", "jquery", "underscore"], function (BB, $, _) { return BB.Model.extend({ idAttribute: "_id", initialize: function () { var that = this; $.ajaxPrefilter( function( options, originalOptions, jqXHR ) { options.crossDomain ={ crossDomain: true }; options.xhrFields = { withCredentials: true }; }); } }); });
现在,当我testing我的代码(让一个POST
请求),我有一个非常特殊的行为:
var contacts = new Contacts; contacts.create({'name': 'my name'});
浏览器返回这个消息:
选项… 404(未find)jquery.js:8419
这完全混淆了我的OPTIONS
http方法不被骨干支持?
大多数情况下,您的Express路由只能指定GET
和/或POST
方法。 例如,
app.post('/some/api/method', function(req, res) { ... });
这意味着您只为POST
定义了一个路由处理程序到/ some / api / method ,并且使用其他方法(如GET
或OPTIONS
)的请求将返回一个404。
在某些情况下(例如发送自定义的HTTP头),XHR使用CORS向跨源URL请求请求浏览器必须首先发出OPTIONS
请求,以查看是否允许跨域请求。 只有在OPTIONS
请求成功的情况下(HTTP 200 带有 CORS头文件),浏览器才会发出实际的请求。
由于您只在服务器上定义了POST
路由,因此OPTIONS
请求失败,浏览器不发出请求。 您需要正确回应OPTIONS
请求:
app.options('/some/api/method', function(req, res) { // At this point, the `allowCrossDomain()` middleware will already have // taken care of the CORS stuff, so just return OK. res.send(200); });
现在,预检OPTIONS
检查将通过,所以对POST
处理程序的真正请求将被执行。
有关您的代码的奖励评论:
- 性能改进:
- 使用一个对象来查找和validation来源,而不是一个数组。 使用
indexOf
需要在每个请求上缓慢迭代数组,在这种情况下使用对象可以快速查找。 (请记住,JavaScript对象将其密钥存储在类似字典的数据结构中。) - 在validation函数之外定义
allowedHosts
– 它们不会更改,因此每次调用allowCrossDomain
(需要垃圾回收)时都不需要创build新对象。
- 使用一个对象来查找和validation来源,而不是一个数组。 使用
- 当跨源检查失败时,您可能应该发送不成功的HTTP响应代码。
var allowedHost = { 'http://localhost:3001': true, 'http://localhost:7357': true }; var allowCrossDomain = function(req, res, next) { if(allowedHost[req.headers.origin]) { res.header('Access-Control-Allow-Credentials', true); res.header('Access-Control-Allow-Origin', req.headers.origin) res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'); next(); } else { res.send(403, {auth: false}); } }