使用CORS的跨域分块上传

时间:2013-02-13 18:18:10

标签: nginx xmlhttprequest cross-domain cors fileapi

我有用户提交的文件,我试图以10 MB的块上传。我目前正在使用原始XMLHttpRequest(和XDomainRequest)来推送前端的每个切片(File.prototoype.slice)。后端是使用upload module的Nginx。

仅供参考,以下是我如何使用slice的简介:

element.files[0].slice(...)

我理解跨浏览器前缀方法webkitSlicemozSlice以及所有这些。

我遇到的问题是实际发出跨域请求。我正在从server.local上传到upload.server.local。在Firefox中,options请求通过正常,然后实际的post失败。在Chrome和Opera中,options请求失败并带有

 OPTIONS https://URL Resource failed to load

以下是Firefox的标题:

请求标题

OPTIONS /path/to/asset HTTP/1.1
Host: upload.server.local:8443
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: https://server.local:8443
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-disposition,content-type,x-content-range,x-session-id
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

响应标头

HTTP/1.1 204 No Content
Server: nginx/1.2.6
Date: Wed, 13 Feb 2013 03:27:44 GMT
Connection: keep-alive
access-control-allow-origin: https://server.local:8443
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: x-content-range, origin, content-disposition, x-session-id, content-type, cache-control, pragma, referrer, host
access-control-allow-credentials: true
Access-Control-Max-Age: 10000

实际的post请求永远不会离开浏览器。 Nginx访问日志永远不会看到post。浏览器出于某种原因暂停了它。我如何解开为什么这篇文章被阻止?

Chromium 24
Firefox 18
Opera 12.14

我已经验证所有浏览器都正确支持CORS here

通过将我的上传内容指向https://cors-test.appspot.com/test,我已经确认问题肯定是服务器端标题。

1 个答案:

答案 0 :(得分:1)

如果preflight check没有返回足够的权限,POST将不会离开浏览器,因此POST请求未获得完全授权。问题中包含的请求/响应确实对我来说足够了。

  • 您确定要在XMLHttpRequest中设置withCredentials = true吗?
  • 您确定服务器上有有效(非自签名)SSL证书吗?即使您添加了使用无效证书浏览站点的例外,HTTPS也可能无法通过CORS检查。
  • 您是否尝试清空缓存?您在响应标头中设置了Access-Control-Max-Age: 10000。那差不多是3个小时。我知道你一直在研究这个问题的时间比这要长,但是在进行特别测试时,请将该标题设置为零,这样你就不会对浏览器缓存旧的访问权限感到疯狂。

一般情况下,我首先要尽可能地使用CORS标头,并慢慢提高安全性以查看其失败的位置。但是,这并非完全直截了当。例如,根据MDN documentation on CORS

  

在响应凭证请求时,服务器必须指定域,并且不能使用通配符。如果标头被通配为:Access-Control-Allow-Origin: *

,则上述示例将失败

当我将问题的请求部分发送到https://cors-test.appspot.com/test时,我会回复以下内容:

HTTP/1.1 200 OK
Cache-Control: no-cache
Access-Control-Allow-Origin: https://server.local:8443
Access-Control-Allow-Headers: content-disposition,content-type,x-content-range,x-session-id
Access-Control-Allow-Methods: POST
Access-Control-Max-Age: 0
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 35
Vary: Accept-Encoding
Date: Thu, 23 May 2013 06:37:34 GMT
Server: Google Frontend

所以你可以从那里开始并添加越来越多的安全性,直到它破裂以找出罪魁祸首。