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 ,并且使用其他方法(如GETOPTIONS )的请求将返回一个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新对象。
  • 当跨源检查失败时,您可能应该发送不成功的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}); } }