根据CORS规范,GET和POST请求应该透明地遵循302重定向。但Chrome正在取消我的请求。
以下是执行请求的JS:
var r = new XMLHttpRequest();
r.open('GET', 'https://dev.mysite.com/rest', true);
r.send();
以下是应该发生的事情:
- 客户端:XHR POST请求到/休息
- 服务器:响应HTTP 302重定向到/rest/
- 客户端:遵循重定向
但在第2步之后,Chrome会取消请求。如果没有HTTP302,那么请求将完美地工作。我已经证实了。
当请求运行时,我可以在Chrome的"网络"面板中看到只有一个XHR——一个取消的POST请求,没有响应头或响应体。
使用Chrome的网络内部工具进行调试时,我看到服务器发送了一个响应,之后请求被取消。以下是请求的输出:
79295: URL_REQUEST
https://dev.mysite.com/rest
Start Time: 2013-08-30 12:41:11.637
t=1377880871637 [st= 0] +REQUEST_ALIVE [dt=13455]
t=1377880871638 [st= 1] URL_REQUEST_BLOCKED_ON_DELEGATE [dt=1]
--> delegate = "extension Adblock Plus"
t=1377880871639 [st= 2] +URL_REQUEST_START_JOB [dt=13453]
--> load_flags = 143540480 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | ENABLE_LOAD_TIMING | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
--> method = "POST"
--> priority = 2
--> upload_id = "0"
--> url = "https://dev.mysite.com/rest"
t=1377880871639 [st= 2] HTTP_CACHE_GET_BACKEND [dt=0]
t=1377880871639 [st= 2] +HTTP_STREAM_REQUEST [dt=7]
t=1377880871646 [st= 9] HTTP_STREAM_REQUEST_BOUND_TO_JOB
--> source_dependency = 79296 (HTTP_STREAM_JOB)
t=1377880871646 [st= 9] -HTTP_STREAM_REQUEST
t=1377880871646 [st= 9] +HTTP_TRANSACTION_SEND_REQUEST [dt=0]
t=1377880871646 [st= 9] HTTP_TRANSACTION_SEND_REQUEST_HEADERS
--> GET /facultyportfolio-rest HTTP/1.1
Host: dev.liberty.edu
Connection: keep-alive
Content-Length: 46
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept: */*
Referer: http://localhost:8080/ajaxtest.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
t=1377880871646 [st= 9] HTTP_TRANSACTION_SEND_REQUEST_BODY
--> did_merge = true
--> is_chunked = false
--> length = 46
t=1377880871646 [st= 9] -HTTP_TRANSACTION_SEND_REQUEST
t=1377880871646 [st= 9] +HTTP_TRANSACTION_READ_HEADERS [dt=1001]
t=1377880871646 [st= 9] HTTP_STREAM_PARSER_READ_HEADERS [dt=1000]
t=1377880872646 [st= 1009] HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 302 Found
Date: Fri, 30 Aug 2013 16:41:11 GMT
Server: Apache/2
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Credentials: true
Location: https://dev.mysite.com/rest/
Content-Language: en-US
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 20
Connection: close
Content-Type: text/plain; charset=UTF-8
t=1377880872647 [st= 1010] -HTTP_TRANSACTION_READ_HEADERS
t=1377880872647 [st= 1010] +URL_REQUEST_BLOCKED_ON_DELEGATE [dt=12445]
t=1377880885091 [st=13454] CANCELLED
t=1377880885092 [st=13455] -URL_REQUEST_START_JOB
--> net_error = -3 (ERR_ABORTED)
t=1377880885092 [st=13455] -REQUEST_ALIVE
最后,您可以看到"取消",因为"URL_REQUEST_BLOCKED_ON_DELEGATE"。我不知道这意味着什么。但是,如果没有HTTP302重定向,错误就不会发生。
有人知道是什么原因导致Chrome取消了这个请求吗?
这里的答案是混合的,暗示了代码等中的某些设置,这可能会解决CORS的重定向问题,但CORS规范明确规定了此类CORS重定向何时失败/通过:根据规范,浏览器应该
- 如果对重定向资源的请求不需要飞行前检查(例如,没有自定义标头的简单CORS请求),则允许3XX重定向。看见https://www.w3.org/TR/cors/#simple-交叉原始请求-0
如果手动重定向标志未设置,并且响应的HTTP状态代码为301302303307或308应用重定向步骤
- 如果对重定向资源的请求需要飞行前检查,则不允许3XX重定向。看见https://www.w3.org/TR/cors/#cross-原始请求-带反光灯-0
如果响应的HTTP状态代码为301302303307或308应用缓存和网络错误步骤。
我在github repo中探索了各种CORS场景:https://github.com/monmohan/cors-experiment.
重定向失败的这个特定问题也可以很容易地通过这里的捆绑包隔离复制:https://github.com/monmohan/cors-experiment/tree/master/issue
我发现这篇关于在302响应上设置正确的Access Control Allow Origin CORS标头的文章很有帮助,至少在我类似的情况下是这样。
对问题的调查表明,他的XHR没有降落在CORS直接启用了URL,但通过HTTP 302(重定向)响应。
请记住,重定向URL还必须包含Access Control Allow Origin标头,否则浏览器将立即停止其尝试的跨域请求。
我还发现,在Access Control Allow Origin之上和之外设置额外的CORS头通常会导致事务被取消。
http://httpstatus.es/302
如果302状态代码是响应GET或HEAD以外的请求而接收的,则用户代理不得自动重定向请求,除非用户能够确认,因为这可能会更改发出请求的条件。
我还遇到了Chrome没有在CORS请求上重定向的问题。对我来说,问题是我使用的JS框架(Sencha Touch)添加了一个请求标头:X-Requested-With:"XMLHttpRequest"
我一删除它(在Sencha Touch中,通过调用Ext.Ajax.setUseDefaultXhrHeader(false);)它就像一个符咒。
不知道为什么,但我希望这些信息能帮助到别人。