我在必要时使用$(document).ajaxSend(...)
动态地向某些Ajax请求添加数据(POST args)。
在$.ajax(...)
调用中定义某些数据时,添加数据会起作用。但如果$.ajax
设置中未定义任何数据,我的$.ajaxSend
无法将数据添加到设置中。
这是我的$.ajaxSend
拦截器:
$(document).ajaxSend(function(e, request, settings) {
if(settings.csrfIntention) {
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
}
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
else if(typeof(settings.data) == 'string') {
settings.data += '&_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
else if(!settings.data._token) {
settings.data._token = requestToken;
}
}
});
一个有效的$ .ajax调用示例:
$.ajax({
url: opts.close.url,
method: 'POST',
data: { foo:'bar' },
csrfIntention: 'ajax_close_ticket',
success: function(data) { ... }
});
$.ajaxSend
有效且settings.data
设置为:
foo=bar&_token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%22uXV1AeZwm-bZL3KlYER-Dowzzd1QmCmaT6aJFjWLpLY%22%7D
Serverside,我可以检索两个字段:foo和_token。
现在,如果我删除data
调用中的$.ajax
对象,$.ajaxSend
的输出似乎也可以:
_token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%225cK2WIegwI6u8K_FrxywuauWOo79xvhIcASQrZ9QPZQ%22%7D
然而,服务器没有收到我的_token字段:(
另一个有趣的事实:当我有两个字段时,网络选项卡下的Chromium开发工具会在"表格数据"下显示两个字段。标题。当_token独自时,"表单数据"被"请求有效负载"。
取代 编辑:只是理解为什么服务器不会解释_token。如果之前未在$.ajax
调用中设置任何数据,则jQuery不会在HTTP标头中添加正确的Content-Type
,而是将其设置为text/plain
而不是application/x-www-form-urlencoded
。如何强制jQuery添加此标头?
修改2:找到解决方案。会发一个答案来帮助其他人......
答案 0 :(得分:0)
我为我糟糕的英语道歉
我相信他的案例的解决方案是使用函数" ajaxSetup"
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
};
$.ajaxSetup({
data : {
_token: requestToken
}
});
这样你所有的订单都将数据作为愿望
答案 1 :(得分:0)
更简单的方法:
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
}
var myForm = {};
myForm['_token'] = encodeURIComponent(JSON.stringify(requestToken));
在你的ajax电话中:
myForm['foo'] = 'bar';
$.ajax({
url: opts.close.url,
method: 'POST',
data: myForm,
csrfIntention: 'ajax_close_ticket',
success: function(data) { ... }
});
//This sends foo and _token
答案 2 :(得分:0)
最后我在10分钟后回答我的问题......
在HTTP中,表单参数被发送到标题下的请求正文中。标题Content-Type
应该存在以声明数据类型。当此标头设置为application/x-www-form-urlencoded
时,服务器将了解您已发送表单并将请求正文解析为GET URL(您知道,foo=bar&key=val
格式)。
当您将data
对象设置为$.ajax
调用时,jQuery会自动添加此标头。然后它将请求传递给$.ajaxSend
回调,后者会添加正确的字段。
如果请求设置中未提供data
,则jQuery不会在请求标头中添加不必要的Content-Type: x-www-form-urlencoded
。然后,当您将请求主体附加到$.ajaxSend
回调中时,jQuery不会再次检查数据并将内容声明为text/plain
。服务器与text/plain
无关,因此它不会将正文数据解释为表单字段。
您显然可以强制jQuery将标题更改为application/x-www-form-urlencoded
,让我们采用原始帖子的代码:
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
现在添加正确的标题:
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}