【问题标题】:Chrome cancels CORS XHR upon HTTP 302 redirectChrome 在 HTTP 302 重定向时取消 CORS XHR
【发布时间】:2013-09-03 13:36:03
【问题描述】:

看起来根据CORS Spec,GET 和 POST 请求应该透明地遵循 302 重定向。但 Chrome 正在取消我的请求。

这是执行请求的 JS:

var r = new XMLHttpRequest();
r.open('GET', 'https://dev.mysite.com/rest', true);
r.send();

以下是应该发生的事情:

  1. 客户端:对 /rest 的 XHR POST 请求
  2. 服务器:响应 HTTP 302 重定向到 /rest/
  3. 客户:遵循该重定向

但在第 2 步之后,Chrome 取消了请求。如果没有 HTTP 302,请求将完美运行。我已经确认了。

当请求运行时,我可以在 Chrome 的网络面板中看到只有一个 XHR - 一个取消的 POST 请求,没有响应标头或响应正文。

使用 Chrome 的 net-internals 工具调试,我看到服务器发送了一个响应,然后请求被取消。这是请求的输出:

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”。我不知道那是什么意思。但同样,如果没有 HTTP 302 重定向,则不会发生错误。

有谁知道是什么导致 Chrome 取消了这个请求?

【问题讨论】:

    标签: google-chrome redirect xmlhttprequest cors .net-internals


    【解决方案1】:

    http://httpstatus.es/302

    如果收到 302 状态代码以响应 GET 或 HEAD 以外的请求,用户代理不得自动重定向请求,除非用户可以确认,因为这可能会改变请求被执行的条件发布。

    【讨论】:

    • 所以这似乎是说 GET 请求应该重定向。我的请求是 GET,但它不会重定向。
    • 你说第 1 步是,“客户端:XHR POST 请求 /rest”
    • 哦,抱歉,是的,问题最初出现在 POST 上,但也出现在 GET 上。也许切换到 303 或 307 HTTP 代码可能会起作用...
    • 请参阅stackoverflow.com/questions/40580913/… 以获得更清晰的解释和规范更新。
    【解决方案2】:

    我还遇到了 Chrome 没有遵循 CORS 请求重定向的问题。对我来说,问题是我使用的 JS 框架(Sencha Touch)添加了一个请求头:X-Requested-With: "XMLHttpRequest"

    一旦我删除了这个(在 Sencha Touch 中通过调用 Ext.Ajax.setUseDefaultXhrHeader(false);),它就像一个魅力。

    不知道为什么,但我希望这些信息对某人有所帮助。

    【讨论】:

      【解决方案3】:

      我发现这篇关于 setting the correct Access-Control-Allow-Origin CORS header on your 302 response 的帖子很有帮助,至少在我听起来类似的情况下是这样。

      问题调查显示他的 XHR 没有登陆 直接启用了 CORS 的 URL,但被重定向到它 HTTP 302(重定向)响应。

      因此请记住,重定向 URL 还必须包含 Access-Control-Allow-Origin 标头,否则浏览器将向右停止 那里有它尝试的跨域请求。

      我还发现,在 Access-Control-Allow-Origin 之外设置额外的 CORS 标头通常会导致交易被取消。

      【讨论】:

      • 我的请求确实收到了 302,但响应包含正确的 Access-Control-Allow-Origin 标头。你说额外的响应头可能会导致取消?您能否再解释一下,或者举例说明是哪些标头导致了它?
      【解决方案4】:

      这里的答案参差不齐,暗示代码等中的某些设置可能会解决 CORS 的重定向问题,但 CORS 规范明确指定了此类 CORS 重定向何时失败/通过: 根据规范,浏览器应该

      1. 如果对重定向资源的请求不需要飞行前检查(例如没有自定义标头的简单 CORS 请求),则允许 3XX 重定向。见https://www.w3.org/TR/cors/#simple-cross-origin-request-0

      如果手动重定向标志未设置且响应的 HTTP 状态代码为 301、302、303、307 或 308 应用重定向步骤

      1. 如果对重定向资源的请求需要飞行前检查,则不允许 3XX 重定向。见https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0

      如果响应的 HTTP 状态代码为 301、302、303、307 或 308 应用缓存和网络错误步骤。

      我在 github repo 中探索了各种 CORS 场景:https://github.com/monmohan/cors-experiment

      这个重定向失败的特定问题也可以通过这里的捆绑包轻松地单独重现:https://github.com/monmohan/cors-experiment/tree/master/issue

      【讨论】:

      • 您是否知道为什么要求预检的请求不允许使用 30x?我很想阅读规范这部分的一些基本原理。
      • 显然,允许的重定向是规范中的“最近更改”(stackoverflow.com/questions/40580913/…),仅在 2016 年 8 月 4 日,因此浏览器需要一段时间才能合规......
      猜你喜欢
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 2011-12-24
      • 2015-05-09
      • 1970-01-01
      • 2014-03-08
      • 1970-01-01
      相关资源
      最近更新 更多