【问题标题】:cross domain CORS support for backbone.js对backbone.js 的跨域CORS 支持
【发布时间】:2012-12-20 13:24:21
【问题描述】:

我正在尝试为我的主干应用实现跨域设置。

我的服务器 (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) 也被配置为接受跨域:

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

现在当我测试我的代码时(比如说POST 请求),我有一个非常特殊的行为:

var contacts = new Contacts;
contacts.create({'name': 'my name'});

浏览器返回此消息:

选项 ... 404(未找到) jquery.js:8419

这完全让我感到困惑,因为主干不支持OPTIONS http 方法?

【问题讨论】:

标签: ajax node.js backbone.js express cors


【解决方案1】:

您的 Express 路由很可能仅指定 GET 和/或 POST 方法。例如,

app.post('/some/api/method', function(req, res) { ... });

这意味着您只为POSTs 定义了一个路由处理程序到/some/api/method,并且使用任何其他方法(如GET 或OPTIONS)的请求将返回 404。

在某些情况下(例如发送自定义 HTTP 标头),使用 CORS 对跨域 URL 的 XHR 请求要求浏览器必须首先发出 OPTIONS 请求以查看是否允许跨域请求。只有OPTIONS 请求成功(HTTP 200 with 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 处理程序发出真正的请求。


关于您的代码的奖励:

  • 性能改进:
    • 使用对象而不是数组来查找和验证来源。使用indexOf 需要在每次请求时对数组进行缓慢的迭代,而使用对象可以快速查找。 (请记住,JavaScript 对象将其键存储在类似字典的数据结构中。)
    • 在验证函数之外定义allowedHosts——它们不会改变,因此无需在每次调用allowCrossDomain 时创建新对象(需要垃圾回收)。
  • 当跨域检查失败时,您可能应该发送一个不成功的 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});
  }
}

【讨论】:

    猜你喜欢
    • 2012-12-24
    • 2012-01-16
    相关资源
    最近更新 更多