Google chrome XMLHttpRequest CORS到Google云存储仅在飞行前请求中工作

Google chrome XMLHttpRequest CORS到Google云存储仅在飞行前请求中工作,google-chrome,xmlhttprequest,cors,google-cloud-storage,Google Chrome,Xmlhttprequest,Cors,Google Cloud Storage,我使用XMLHttpRequest发送到服务器端创建的可恢复上传url,实现了基于浏览器的可恢复上传到Google的云存储中。当我在开发过程中禁用web安全性时,这完全可以正常工作 但现在在现实世界中,CORS不断制造麻烦。我也在其他浏览器上尝试过(没有成功),但坚持使用chrome进行进一步测试 注意:/etc/HOSTS中的false.host条目用于欺骗chrome避免本地主机限制。然而,在线测试服务器的“真实”域也是如此 使用普通的XMLHttpRequest调用启动请求: var xh

我使用XMLHttpRequest发送到服务器端创建的可恢复上传url,实现了基于浏览器的可恢复上传到Google的云存储中。当我在开发过程中禁用web安全性时,这完全可以正常工作

但现在在现实世界中,CORS不断制造麻烦。我也在其他浏览器上尝试过(没有成功),但坚持使用chrome进行进一步测试

注意:
/etc/HOSTS
中的
false.host
条目用于欺骗chrome避免本地主机限制。然而,在线测试服务器的“真实”域也是如此

使用普通的XMLHttpRequest调用启动请求:

var xhr = this.newXMLHttpRequest();
xhr.open('PUT', url, true);

xhr.setRequestHeader('Content-Type', this.currentInputFile.type);
xhr.setRequestHeader('Content-Range', 'bytes ' + startByte + '-' + (this.currentInputFile.size - 1) + '/' + this.currentInputFile.size);

xhr.onload = function(e) {
   ...
};

...

if (startByte > 0) {
    xhr.send(this.currentInputFile.slice(startByte));
} else {
    xhr.send(this.currentInputFile);
}
浏览器随后成功启动飞行前请求:

Remote Address:173.194.71.95:443
Request URL:https://www.googleapis.com/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
Request Method:OPTIONS
Status Code:200 OK
请求标头:

:host:www.googleapis.com
:method:OPTIONS
:path:/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
:scheme:https
:version:HTTP/1.1
accept:*/*
accept-encoding:gzip,deflate
accept-language:en-US,en;q=0.8,de;q=0.6
access-control-request-headers:content-range, content-type
access-control-request-method:PUT
origin:https://fake.host
referer:https://fake.host/upload.xhtml
user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36
x-client-data:YYYYYY
查询字符串参数

uploadType:resumable
name:aa spacetestSMALL_512kb.mp4
upload_id:XXXXXXXXX
响应头

access-control-allow-credentials:true
access-control-allow-headers:content-range, content-type
access-control-allow-methods:PUT
access-control-allow-origin:https://fake.host
alternate-protocol:443:quic
content-length:0
content-type:text/html; charset=UTF-8
date:Fri, 05 Sep 2014 14:11:21 GMT
server:UploadServer ("Built on Aug 18 2014 11:58:36 (1408388316)")
status:200 OK
version:HTTP/1.1
。。。并启动PUT请求,直到传输所有数据。但之后chrome会在不完成/结束请求的情况下以静默方式记录错误:

XMLHttpRequest无法加载…XXXXXXXX。请求的资源上不存在“Access Control Allow Origin”标头。因此,不允许访问源“”

这是chrome记录的关于PUT请求的内容:

Request URL:https://www.googleapis.com/upload/storage/v1/b/my-bucket-name/o?uploadType=resumable&name=aa%20spacetestSMALL_512kb.mp4&upload_id=XXXXXXXXX
请求头

Provisional headers are shown
Content-Range:bytes 0-3355302/3355303
Content-Type:video/mp4
Origin:https://fake.host
Referer:https://fake.host/upload.xhtml
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id:YYYYYYY
查询字符串

uploadType:resumable
name:aa spacetestSMALL_512kb.mp4
upload_id:XXXXXXXXX
值得注意的是,当在中添加相同的url并发出任何请求时,除了
选项
请求类型之外,其他所有请求类型都会失败。云存储api似乎只为选项请求发出正确的响应头,而不是PUT/POST/GET/。。。请求

那么我是在做一些不可能的事情吗?有东西坏了吗?这是云存储api中的一个bug吗?我已经花了几个小时在谷歌上搜索和阅读了这么多的答案,到目前为止我一点运气都没有


现在,我可以定期检查下载是否传输了100%的数据,而忽略http请求结果,因为文件实际上已完全上载到存储桶。但这是一个相当丑陋的解决方法,如果真正的问题能够得到解决,我真的不想使用它。

因为这个问题仍然没有答案,而且仍然有相当多的观点,我将尝试在这里发布一些明确的东西

响应上传数据的任何PUT请求时返回的
'Access-Control-Allow-Origin'
标头始终设置为中给出的用于启动上传的
来源,如下所示:

使用可恢复上载协议时,第一个 (开始上传)请求始终用于决定 访问控制允许响应中的原始标头,即使使用 后续请求的不同来源。因此,你应该 对于第一个和后续请求,或者如果 第一个请求与后续请求的来源不同,请使用 CORS配置设置为*的XML API

这意味着您必须在发送数据的任何PUT请求之前发送初始POST请求,并且任何后续PUT请求必须与初始POST具有相同的“来源”

关于GCS中的CORS配置集,这仅适用于从以下位置调用XML API:

注意:CORS配置仅适用于XML API请求。对于JSON API请求时,云存储始终返回 带有请求来源的Access Control Allow Origin标头


当请求一个可恢复的上传url时,您必须包括浏览器在尝试使用该上传url时将发送的来源,否则后续上传将失败,正如问题中所发生的那样(选项调用看起来不错,但看跌期权不会)

它必须与浏览器的源代码完全匹配(在javascript中可以作为location.origin获得)

这是本文档中的“启动可恢复上传会话”步骤:

如果您在服务器端请求可恢复的上传url,则可能需要客户端(浏览器)向您传递其来源(例如:location.origin)

fwiw我在这一步中使用了Google的python云存储库,需要添加如下来源:

myblob.create_resumable_upload_session(mycontenttype, origin=browserorigin)

请注意,您绝对不需要为您的铲斗设置CORS。

您在地面军事系统上设置过CORS吗?当然可以。我想如果没有它,飞行前的请求会失败,但事实并非如此。只有上传文件后的最终响应无效。能否显示您使用的json?感觉你忘记了“方法”:[“PUT”,“POST”,“GET”],我正在使用java API:看起来这可能是一个已知的问题:我想这在3年前是不可能的,但现在似乎是正确的解决方案。2016年有关于该问题的git问题(即)。谢谢花了这么长时间。