使用跨源资源共享的跨域 POST 查询没有返回数据
我通过 POST 请求跨域发送数据,但响应不起作用,具体来说,jQuery 的成功处理程序永远不会被调用。
使用的东西:Django、Apache、jQuery。
因此,我设置了一个与此类似的请求:
$.ajax({
url: "http://somesite.com/someplace",
type: "POST",
cache: false,
dataType: "json",
data: { ... },
success: function( msg ) {
alert(msg);
},
});
正如您所知, CORS 允许我要适当地回应 OPTIONS
查询,说“是的,你可以 POST 给我”。我正在做的事。 Firebug 确认我收到了 200
状态代码,并且返回类型实际上是 application/json
。但是,Firebug 还确认上面的成功处理程序没有被调用。
作为参考,我对 OPTIONS 的回应是:
elif request.method == "OPTIONS":
response = HttpResponse("")
response['Access-Control-Allow-Origin'] = "*"
response['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS"
response['Access-Control-Allow-Headers'] = "X-Requested-With"
return response
相反,如果我设置了一个complete: function()... 处理程序,它就可以工作。
所以,问题是:发生了什么(或没有发生)以及为什么?我得到的数据很好,我只想能够返回响应。
更新:这解决了我在某些浏览器上的问题,但由于我对此行为没有完整明确的解释,因此我将其保持打开状态。
好的,所以我阅读了手册以及我对它的理解,所应用的算法大致是this:
- 用户代理可以实现预检调用。这是
OPTIONS
请求。这个想法是,他们发出这个请求,为他们提供有关所请求资源的答案,然后他们应该缓存该资源。 我没有传回 max-age 字段,因此我怀疑虽然返回成功并且允许 X 请求,但用户代理的缓存中没有任何内容允许我进行此操作,因此应用默认规则(隔离请求)。 - 当您发出实际请求时,我相信用户代理应该检查飞行前缓存的权限。如果没有我的 max-age 字段,我相信它找不到这些权限。但是,在
POST
上使用相同的标头进行响应似乎允许 Firefox 和 Google Chrome 查看响应。歌剧不能。 IE 目前尚未经过测试。
我目前不明白,并且从手册中也不清楚(至少对我来说)CORS 请求是否也应该使用请求中的这些标头以及 OPTIONS 进行应答。我将尝试使用 Max-Age
标头,看看允许或不允许什么。然而,我对这个问题仍然缺乏一些明确的权威理解,所以如果这里有人知道的话,我洗耳恭听。
I'm sending data cross domain via a POST request but the response isn't working, specifically, jQuery's success handler never gets called.
Stuff being used: Django, Apache, jQuery.
So, I set up a request rather similar to this:
$.ajax({
url: "http://somesite.com/someplace",
type: "POST",
cache: false,
dataType: "json",
data: { ... },
success: function( msg ) {
alert(msg);
},
});
As you well know, CORS allows me to respond to an OPTIONS
query appropriately to say "Yes, you can POST to me". Which I'm doing. Firebug confirms I'm getting my 200
status code and that the return type is in fact application/json
. However, Firebug also confirms that the success handler in the above is not being called.
For reference, my response to OPTIONS
is:
elif request.method == "OPTIONS":
response = HttpResponse("")
response['Access-Control-Allow-Origin'] = "*"
response['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS"
response['Access-Control-Allow-Headers'] = "X-Requested-With"
return response
In contrast, if I set up a complete: function()...
handler it works.
So, question is: what's happening (or not) and why? I am getting data fine, I'd just like to be able to return the response.
Update: This fixes my issue on some browsers but since I don't have a complete definite explanation to this behaviour I'm leaving it open.
Ok, so I read the manual and what I understand of it, the algorithm applied is roughly this:
- User agents may implement a preflight call. This is the
OPTIONS
request. The idea is that they make this request which gives them an answer with respect to the requested resource, which they are then supposed to cache. I'm not passing back a max-age field, so I suspect whilst success is being returned and the X-request allowed, there is nothing in the user agent's cache which permitted me to make it, so the default rules (isolate the request) are applied. - When you make the actual request, I believe the user agent is supposed to inspect the pre-flight cache for permissions. Without my max-age field, I believe it isn't finding these permissions. However, responding with the same headers on
POST
appears to allow Firefox and Google Chrome to view the response. Opera can not. IE remains untested at the moment.
I do not currently understand and it is not clear from the manual (to me at least) whether a CORS request should also answer with these headers in the request as well as the OPTIONS
. I shall experiment with the Max-Age
header and see what that allows or does not allow. However, I'm still short of some definite authoritative understanding on the issue so if there is someone on here who knows, I'm all ears.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好的,所以我相信正确的做事方法是这样的:
这是基于我从 Mozilla 挖出的文档 关于预检请求。
所以,我相信会发生的是这样的:
OPTIONS
并将X-Requested-With
设置为XMLHttpRequest
> 我相信这是允许 Javascript 访问任何内容以及Origin
标头所必需的。X-Requested-With
”。我是说允许OPTIONS
和POST
,并且该响应应该缓存 30 分钟。Allow-Methods
和Allow-Headers
但根据上面链接文档中的交换,这是不需要的。这是有道理的,访问检查已经完成。Allow-Origin
字段的有效性,这是针对POST
等请求的。如果通过,则客户端可以访问数据,如果没有,则请求已完成,但浏览器拒绝实际的客户端应用程序 (Javascript) 访问该数据。我相信这是对正在发生的事情的正确总结,并且无论如何它似乎都是有效的。如果我说得不对,请大声喊叫。
Ok, so I believe the correct way to do things is this:
This is based on the documentation I dug up from Mozilla on preflighted requests.
So, what I believe will happen is this:
OPTIONS
is sent withX-Requested-With
set toXMLHttpRequest
I believe this is necessary to allow Javascript access to anything, along with anOrigin
header.X-Requested-With
thing". I'm saying thatOPTIONS
andPOST
are allowed and that this response should be cached for 30 mins.Allow-Methods
andAllow-Headers
but according to the exchange in the above linked documentation this isn't needed. This makes sense, the access check has already been done.Allow-Origin
field for validity, this being on the request such asPOST
. If this passes, the client can have access to the data, if not, the request has already completed but the browser denies the actual client side application (Javascript) access to that data.I believe that is a correct summary of what is going on and in any case it appears to work. If I'm not right, please shout.
对于任何可能遇到此帖子的未来搜索者,以下资源是 W3C 2008 工作草案,其中深入讨论了 CORS。
http://www.w3.org/TR/2008/WD- access-control-20080912/
截至本文发布时,应该指出的是,特别是 Chromium,甚至可能所有 WebKit 都有一个错误,该错误会阻止
Access-Control-Max-Age
标题的价值得到尊重。有关详细信息,请参阅 Chromium 问题 131368。总之 - 截至目前,基于 WebKit 的浏览器将使用600
(10 分钟)覆盖服务器返回的任何值。For any future searchers who may come across this posting, the following resource is the W3C 2008 working-draft which discusses CORS in-depth.
http://www.w3.org/TR/2008/WD-access-control-20080912/
As of the time of this posting, it should be noted that Chromium specifically, and probably all of WebKit has a bug which prevents the
Access-Control-Max-Age
header's value from being honored. Details on this can be found on the discussion page for Chromium Issue 131368. In summary - as of now, WebKit-based browsers will override whatever the server returns as a value here with600
(10 minutes).请求:
响应:
REQUEST:
RESPONSE:
出于安全原因,我认为这是不可能的。浏览器允许的唯一跨域 ajax 调用可以使用 JSONP 来完成,并且这些都是专门的 GET 请求。
这会起作用:
这不会:
I don't think this is possible for security reasons. The only cross domain ajax calls which browsers allow, can be done using JSONP and these are exclusively GET requests.
This will work:
This won't: