对backbone.js 的跨域CORS 支持
Posted
技术标签:
【中文标题】对backbone.js 的跨域CORS 支持【英文标题】:cross domain CORS support for backbone.js 【发布时间】: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 方法?
【问题讨论】:
OPTIONS 调用是预检请求:developer.mozilla.org/en-US/docs/HTTP/… 【参考方案1】:您的 Express 路由很可能仅指定 GET
和/或 POST
方法。例如,
app.post('/some/api/method', function(req, res) ... );
这意味着您只为POST
s 定义了一个路由处理程序到/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);
【讨论】:
以上是关于对backbone.js 的跨域CORS 支持的主要内容,如果未能解决你的问题,请参考以下文章