我正在构建一个基于Backbone.js的应用程序并面临一个奇怪的问题。
在某个时刻,应用程序会请求收集资源,而在Chrome(和Safari)中,我会收到类似的错误:
XMLHttpRequest cannot load http://api.mydomain.net/v1/foos/00000d/bars/000014/boots Origin http://localhost:3501 is not allowed by Access-Control-Allow-Origin.
好的,CORS问题我认为并指责我的API。然后通过CURL请求这个资源:
curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XOPTIONS 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots'
HTTP/1.1 200 OK
Status: 200
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Auth-Token
Content-Length: 0
看起来不错,现在是GET:
curl -i -H'Accept: application/json' -H'X-Auth-Token: pAWp5hrCmXA83GgFzgHC' -XGET 'http://api.mydomain.net/v1/foos/00000d/bars/000014/boots'
HTTP/1.1 204 No Content
Status: 204
Cache-Control: no-cache
Content-Length: 0
Content-Type: text/plain
如果我请求包含至少一个对象的靴子集合,一切正常。我认为,我的服务器响应arr完全正常的CORS标头。那么为什么浏览器会报告跨源资源问题呢?
是否归因于我的204回复的内容类型text/plain
?
答案 0 :(得分:10)
您还必须在第二个请求的响应标头中包含Access-Control-Allow-Origin
。这不是客户端问题,而是后端问题。
此行为符合CORS specification,适用于以下说明(section 7.1.5 "Cross-Origin Request with Preflight"):
您的请求在resource sharing check的第一步已失败:
Access-Control-Allow-Origin
标头值,则返回失败并终止此算法。我提供了一个简单的NodeJS示例来说明您的问题 您当前的后端表现如下:
require('http').createServer(function(request, response) {
if (request.method == 'OPTIONS') { // Handle preflight
response.writeHead(200, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "X-Foo"
});
} else { // Handle actual requests
response.writeHead(204, {
//"Access-Control-Allow-Origin": "*"
});
}
response.end();
}).listen(12345);
现在,提出请求并遇到失败:
var x = new XMLHttpRequest;
x.open('GET', 'http://localhost:12345');
x.setRequestHeader('X-Foo','header to trigger preflight');
x.send();
返回我提供的代码,并在响应中启用Access-Control-Allow-Origin
标头,然后再次测试。您的请求现在将成功。