一个CORS POST请求从普通的javascript工作,但为什么不与jQuery?

我正在尝试创build一个“跨源”发布请求,并且我使用如下简单的Javascript工作:

var request = new XMLHttpRequest(); var params = "action=something"; request.open('POST', url, true); request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");}; request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); request.setRequestHeader("Content-length", params.length); request.setRequestHeader("Connection", "close"); request.send(params); 

但我想使用jQuery,但是我无法使它工作。 这就是我想要的:

 $.ajax(url, { type:"POST", dataType:"json", data:{action:"something"}, success:function(data, textStatus, jqXHR) {alert("success");}, error: function(jqXHR, textStatus, errorThrown) {alert("failure");} }); 

这导致失败。 如果有人知道为什么jQuery不起作用,请让我们都知道。 谢谢。

(我使用的是jQuery 1.5.1和Firefox 4.0,而我的服务器正在响应一个正确的Access-Control-Allow-Origin头)

更新:正如TimK指出的,这不再需要jQuery 1.5.2。 但是,如果您想添加自定义标题或允许使用凭据(用户名,密码或cookie等),请继续阅读。


我想我find了答案! (4小时后又诅咒了很多)

 //This does not work!! Access-Control-Allow-Headers: * 

您需要手动指定您将接受的所有标题(至lessFF 4.0和Chrome 10.0.648.204中是这种情况)。

jQuery的$ .ajax方法为所有跨域请求发送“x-requested-with”头(我认为它是唯一的跨域)。

因此,对OPTIONS请求做出响应的缺less头部是:

 //no longer needed as of jquery 1.5.2 Access-Control-Allow-Headers: x-requested-with 

如果你传递任何非简单的标题,你将需要把它们包含在你的列表中(我发送一个):

 //only need part of this for my custom header Access-Control-Allow-Headers: x-requested-with, x-requested-by 

所以把它放在一起,这里是我的PHP:

 // * wont work in FF w/ Allow-Credentials //if you dont need Allow-Credentials, * seems to work header('Access-Control-Allow-Origin: http://www.example.com'); //if you need cookies or login etc header('Access-Control-Allow-Credentials: true'); if ($this->getRequestMethod() == 'OPTIONS') { header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); header('Access-Control-Max-Age: 604800'); //if you need special headers header('Access-Control-Allow-Headers: x-requested-with'); exit(0); } 

另一种可能性是设置dataType: json导致JQuery发送Content-Type: application/json头。 这被CORS认为是一个非标准的标题,并且需要一个CORS预检请求。 所以有几件事要尝试:

1)尝试configuration您的服务器发送适当的预检响应。 这将以附加标题的forms出现,比如Access-Control-Allow-MethodsAccess-Control-Allow-Headers

2)删除dataType: json设置。 JQuery应该默认请求Content-Type: application/x-www-form-urlencoded ,但是可以确定的是,你可以用contentType: 'application/x-www-form-urlencoded'replacedataType: json contentType: 'application/x-www-form-urlencoded'

你在js中发送“params”: request.send(params);

但“jquery中的数据”。是数据定义?: data:data,

另外,您在url中有错误:

 $.ajax( {url:url, type:"POST", dataType:"json", data:data, success:function(data, textStatus, jqXHR) {alert("success");}, error: function(jqXHR, textStatus, errorThrown) {alert("failure");} }); 

你正在把语法和$ .post的语法混合在一起


更新 :我基于monsur的回答search,我发现你需要添加Access-Control-Allow-Headers: Content-Type (下面是完整的段落)

http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/

CORS如何工作

CORS与Flash的crossdomain.xml文件非常类似。 基本上,浏览器将发送一个跨域请求到一个服务,设置HTTP头Origin到请求服务器。 该服务包含一些标题,如Access-Control-Allow-Origin来指示是否允许这样的请求。

对于BOSH连接pipe理器,通过将Access-Control-Allow-Origin的值设置为*,可以指定允许所有的源。 Content-Type头还必须在Access-Control-Allow-Headers头中被列入白名单。

最后,对于某些types的请求(包括BOSH连接pipe理器请求),权限检查将被预先考虑。 浏览器将执行OPTIONS请求,并期望获得一些HTTP标头,指明允许哪些来源,允许哪些方法以及授权持续多久。 例如,下面是我所做的旁遮普语和ejabberd补丁返回的选项:

 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: Content-Type Access-Control-Max-Age: 86400