Ext.Ajax.request vs model.save cross origin cookies



我在model.save没有通过跨源请求发送 cookie 时遇到了问题,但Ext.Ajax.request发送回 cookie 没有问题。 在我们的本地开发中,我们覆盖所有 Ajax 请求(包括模型操作(上的 beforerequest 以设置withCredentials = trueuseDefaultXhrHeader = false,这有助于在正常的 Ext.Ajax.request 上使用 CORS。

据我了解,拥有ajax类型的代理类似于执行 Ext.Ajax.request,这很明显,因为 model.save 命中了 beforerequest(您将在下面的示例中看到这一点(。 您还会注意到,在示例中,model.save 首先发送一个 OPTIONS 调用,然后从不跟进 POST(但这很可能是因为服务器(......无论哪种方式,OPTIONS而不是POST似乎都有点可疑。

下面是示例:

Ext.Ajax.on({
beforerequest: function (conn, options, eOpts) {
console.log('here', conn, options)
options.useDefaultXhrHeader = false;
options.withCredentials = true;
}
});
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: ['test'],
proxy: {
type: 'ajax',
url: 'https://docs.sencha.com'
}
});
var model = Ext.create('MyModel');
// This will fire off an OPTIONS call and not send the cookies
model.save();
// This will fire off with the POST and send the cookies
Ext.Ajax.request({
url: 'https://docs.sencha.com',
method: 'POST'
});

有没有办法让 model.save 将 cookie 发送到跨域?

不,您无法绕过OPTIONS请求。

一旦您向 POST 请求添加有效负载,浏览器就会开始发送OPTIONS请求,就像model.save()一样。如果您稍微更改Ext.Ajax.request操作以匹配model.save操作,也会发生这种情况:

// This will fire off an OPTIONS request.
Ext.Ajax.request({
url: 'https://docs.sencha.com',
method: 'POST',
jsonData: {id: "MyModel-1"}
});

OPTIONS请求是所谓的"预检请求",旨在从服务器获取服务器是否允许实际跨源请求的信息。服务器必须肯定地回答这个问题,包括包含一组 CORS 标头的 Http 响应标头。docs.sencha.com确实应答了OPTIONS请求,但它不会返回所需的标头,因此您会在浏览器控制台中找到一条错误消息:

XMLHttpRequest 无法加载 https://docs.sencha.com/?_dc=1499412133932。请求的资源上不存在"访问控制允许源"标头。因此,不允许访问源"https://fiddle.sencha.com"。

作为反例,我启用了 CORS 的后端向客户端发送以下标头:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, X-Requested-With
  • Origin包含可能从中发送 CORS 请求的所有域,或 * 表示所有域。
  • Methods包含所有允许的方法,则至少需要OPTIONS, POST.
  • Headers包含您的请求可能发送到服务器的所有标头。Chrome 控制台会告诉您是否缺少浏览器期望的;至少我是这样进入我的名单的。

如果在OPTIONS请求中满足这些条件,则将发送实际的POST请求;否则,您将在浏览器控制台中找到所述错误消息。

感谢 Mitchell Simoens 在 Sencha 论坛上,他帮助我找出了问题的根本原因,即代理的作者。 我需要创建一个自定义编写器来解决此问题。

小提琴:

Ext.define('Ux.data.writer.Json', {
extend : 'Ext.data.writer.Json',
alias  : 'writer.ux-json',
config : {
/**
* @cfg {Boolean} useJsonData
* If {@link #allowSingle} is `true` and only one model is being
* saved, this will control if the request will set the data using
* `params` or `jsonData`.
*/
useJsonData : false
},
writeRecords: function(request, data) {
var me = this,
root = me.getRootProperty(),
transform = this.getTransform(),
json, single;
if (me.getExpandData()) {
data = me.getExpandedData(data);
}
if (me.getAllowSingle() && data.length === 1) {
// convert to single object format
data = data[0];
single = true;
}
if (transform) {
data = transform(data, request);
}
if (me.getEncode()) {
if (root) {
// sending as a param, need to encode
request.setParam(root, Ext.encode(data));
} else {
//<debug>
Ext.raise('Must specify a root when using encode');
//</debug>
}
} else if (single && !me.getUseJsonData()) {
request.setParams(Ext.apply(request.getParams(), data));
} else if (single || (data && data.length)) {
// send as jsonData
json = request.getJsonData() || {};
if (root) {
json[root] = data;
} else {
json = data;
}
request.setJsonData(json);
}
return request;
}
});
Ext.Ajax.on({
beforerequest: function (conn, options, eOpts) {
console.log(options.url, options);
options.useDefaultXhrHeader = false;
options.withCredentials = true;
}
});
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: ['blah'],
proxy: {
type: 'ajax',
url: 'https://docs.sencha.com',
writer: {
type: 'ux-json'
}
}
});
var model = Ext.create('MyModel', {
blah : 2
});
model.save();
Ext.Ajax.request({
url: 'https://docs.sencha.com',
method: 'POST',
params: {
blah: 1
}
});

相关内容

  • 没有找到相关文章

最新更新