Javascript 使用跨域资源共享的跨域 POST 查询不返回任何数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5251689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross domain POST query using Cross-Origin Resource Sharing getting no data back
提问by
I'm sending data cross domain via a POST request but the response isn't working, specifically, jQuery's success handler never gets called.
我通过 POST 请求跨域发送数据,但响应不起作用,特别是 jQuery 的成功处理程序永远不会被调用。
Stuff being used: Django, Apache, jQuery.
使用的东西: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, CORSallows 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 notbeing called.
如您所知,CORS允许我OPTIONS
适当地回复查询以说“是的,您可以向我发送邮件”。我在做什么。Firebug 确认我正在获取我的200
状态代码并且返回类型实际上是application/json
. 但是,Firebug 也确认上面的成功处理程序没有被调用。
For reference, my response to OPTIONS
is:
作为参考,我的回应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
In contrast, if I set up a complete: function()...
handler it works.
相比之下,如果我设置了一个complete: function()...
处理程序,它就可以工作。
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 manualand 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-agefield, 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.
- 用户代理可以实现预检调用。这是
OPTIONS
请求。这个想法是他们发出这个请求,给他们一个关于所请求资源的答案,然后他们应该缓存。我没有传回 max-age字段,所以我怀疑在返回成功并允许 X 请求时,用户代理的缓存中没有任何内容允许我创建它,因此默认规则(隔离请求) 的应用。 - 当您发出实际请求时,我相信用户代理应该检查飞行前缓存的权限。如果没有我的 max-age 字段,我相信它找不到这些权限。但是,使用相同的标头进行响应
POST
似乎允许 Firefox 和 Google Chrome 查看响应。歌剧不能。IE 目前尚未经过测试。
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.
我目前不明白,并且从手册中(至少对我而言)不清楚 CORS 请求是否也应该在请求中使用这些标头以及OPTIONS
. 我将试验Max-Age
标题,看看允许或不允许的内容。但是,我对这个问题仍然缺乏一些明确的权威理解,所以如果这里有人知道,我全神贯注。
回答by
Ok, so I believe the correct way to do things is this:
好的,所以我相信正确的做事方法是这样的:
if request.method == "POST":
response = HttpResponse(simplejson.dumps(data),mimetype='application/json')
response['Access-Control-Allow-Origin'] = "*"
return response
elif request.method == "OPTIONS":
response = HttpResponse("")
response['Access-Control-Allow-Origin'] = "*"
response['Access-Control-Allow-Methods'] = "POST, OPTIONS"
response['Access-Control-Allow-Headers'] = "X-Requested-With"
response['Access-Control-Max-Age'] = "1800"
else:
return HttpResponseBadRequest()
This is based on the documentation I dug up from Mozillaon preflighted requests.
这是基于我根据预检请求从 Mozilla 挖出的文档。
So, what I believe will happen is this:
所以,我相信会发生的是:
- If there's nothing in the preflight cache,
OPTIONS
is sent withX-Requested-With
set toXMLHttpRequest
I believe this is necessary to allow Javascript access to anything, along with anOrigin
header. - The server can examine that information. That is the security of CORS. In my case, I'm responding with "any origin will do" and "you're allowed to send the
X-Requested-With
thing". I'm saying thatOPTIONS
andPOST
are allowed and that this response should be cached for 30 mins. - The client then goes ahead and makes the POST, which was working before.
- I modified the response originally to include
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. - I believe then that what happens is the resource sharing check described here. Basically, once said request has been made, the browser again checks the
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.
- 如果预检缓存中没有任何内容,
OPTIONS
则使用X-Requested-With
set 发送XMLHttpRequest
我相信这是允许 Javascript 访问任何内容以及Origin
标题所必需的。 - 服务器可以检查该信息。这就是 CORS 的安全性。就我而言,我的回应是“任何来源都可以”和“您可以发送该
X-Requested-With
东西”。我是说,OPTIONS
并且POST
是允许的,并且此响应应缓存 30 分钟。 - 客户端然后继续并进行 POST,这是之前工作的。
- 我修改了最初的响应以包含
Allow-Methods
,Allow-Headers
但根据上述链接文档中的交换,这是不需要的。这是有道理的,访问检查已经完成。 - 我相信发生的事情就是这里描述的资源共享检查。基本上,一旦提出了所述请求,浏览器就会再次检查该
Allow-Origin
字段的有效性,这是针对诸如POST
. 如果通过,客户端可以访问数据,否则,请求已经完成,但浏览器拒绝实际客户端应用程序 (Javascript) 访问该数据。
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.
我相信这是对正在发生的事情的正确总结,无论如何它似乎都有效。如果我说的不对,请大喊大叫。
回答by Troy Alford
For any future searchers who may come across this posting, the following resource is the W3C 2008 working-draft which discusses CORS in-depth.
对于可能会遇到此帖子的任何未来搜索者,以下资源是 W3C 2008 工作草案,其中深入讨论了 CORS。
http://www.w3.org/TR/2008/WD-access-control-20080912/
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 with 600
(10 minutes).
截至本文发布时,应该注意的是 Chromium 尤其是所有的 WebKit 都有一个错误,该错误阻止了Access-Control-Max-Age
标头的值得到尊重。有关详细信息,请参见Chromium 问题 131368的讨论页面。总之——截至目前,基于 WebKit 的浏览器将覆盖服务器返回的任何值600
(10 分钟)。
回答by Hassan Zaheer
REQUEST:
要求:
$.ajax({
url: "http://localhost:8079/students/add/",
type: "POST",
crossDomain: true,
data: JSON.stringify(somejson),
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
alert(resp.status);
},
error: function (xhr, status) {
alert("error");
}
});
RESPONSE:
回复:
response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")
return response
回答by AyKarsi
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.
我认为出于安全原因这是不可能的。浏览器允许的唯一跨域 ajax 调用可以使用 JSONP 完成,这些都是 GET 请求。
This will work:
这将起作用:
$.ajax({
url: "http://somesite.com/someplace",
type: "GET",
cache: false,
dataType: "JSONP",
data: { ... },
success: function( msg ) {
alert(msg);
},
});
This won't:
这不会:
$.ajax({
url: "http://somesite.com/someplace",
type: "POST",
cache: false,
dataType: "JSONP",
data: { ... },
success: function( msg ) {
alert(msg);
},
});