为啥 Chrome 会取消 CORS OPTION 请求

Posted

技术标签:

【中文标题】为啥 Chrome 会取消 CORS OPTION 请求【英文标题】:Why Chrome cancel CORS OPTION request为什么 Chrome 会取消 CORS OPTION 请求 【发布时间】:2013-02-13 11:25:12 【问题描述】:

在我的应用程序中,我正在创建从 HTTP 到 HTTPS 的 AJAX 请求。这意味着我需要 CORS。因此,我向 jQuery.ajax 添加了一些标头和参数并对其进行了测试。在 Firefox 中一切正常,但在 Chrome 中却不行。 Chrome “杀死”每个预请求的请求(选项)。

jQuery 脚本:

$(document).on('click', 'a.ajax', function(e) 
    e.preventDefault();
    $.ajax(this.href, 
        type: 'GET',
        dataType: 'json',
        crossDomain: false,
        headers: 'X-Requested-With': 'XMLHttpRequest',
        xhrFields: 
            withCredentials: true
        
    );
    return false;
);

HTTP 转储:

> OPTIONS /foo HTTP/1.1
> User-Agent: curl/7.29.0
> Host: local.bar.cz
> Accept: */*
> Access-Control-Request-Headers:accept, origin, x-requested-with
> Access-Control-Request-Method:GET
> Origin:http://local.bar.cz
> 
< HTTP/1.1 204
< Server: nginx/1.2.7
< Date: Wed, 27 Feb 2013 15:06:54 GMT
< Content-Type: text/html; charset=utf-8
< Connection: keep-alive
< X-Powered-By: Nette Framework
< X-Frame-Options: SAMEORIGIN
< Access-Control-Allow-Origin: http://local.bar.cz
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: accept, origin, x-requested-with
< Access-Control-Allow-Methods: OPTIONS, GET, POST, HEAD
< 

有人知道为什么 chrome 会终止这个请求吗?

【问题讨论】:

Chrome“杀死”请求是什么意思?如果您在 Chrome 的控制台和网络选项卡中查看请求,您会看到哪些错误?是实际发出请求,还是预检失败? 在 Chrome 的网络选项卡控制台中,我有状态为 (canceled) 的预检 (OPTIONS) 请求。 尝试清除您的X-Requested-With 字段,将其设为“” 【参考方案1】:

也许您的 https 服务器有一个不受信任的证书。如果是这样,请先尝试使用浏览器访问该 URL,并接受不受信任的连接。

【讨论】:

正是如此。我有同样的情况 - 带有虚拟自签名证书的 NodeJS 服务器。在我的浏览器中打开 URL 后一切正常,Chrome 停止取消我的 OPTIONS 请求。 顺便说一句,小心使用 CORS、自签名证书和 Google Chrome/Chromium。我刚刚为此浪费了一上午:code.google.com/p/chromium/issues/detail?id=141839【参考方案2】:

接受证书并不总能解决这个问题。如果您使用自签名证书,即使您先接受它,Chrome 在某些情况下仍会取消您的预检 OPTIONS 请求。自 2011 年以来一直如此:

https://code.google.com/p/chromium/issues/detail?id=96007

该页面中提到的解决方法是将自签名证书添加到系统的受信任证书列表中。

在 Mac 上执行此操作的说明(对原始版本稍作修改,使其适用于 OS 10.8.5 http://www.robpeck.com/2010/10/google-chrome-mac-os-x-and-self-signed-ssl-certificates/):

    在地址栏中,单击带有 X 的小锁。这将打开一个小信息屏幕。 点击“证书信息”按钮。 单击证书图像并将其拖动到您的桌面一个打开的查找器窗口(它似乎不喜欢拖动到桌面。 双击创建的文件。这将打开钥匙串访问实用程序。输入您的密码以将其解锁。 确保将证书添加到系统钥匙串,而不是登录钥匙串。点击“始终信任”,即使这似乎没有任何作用。 添加后,双击它。您可能需要重新进行身份验证。 展开“信任”部分。 “使用此证书时”设置为“始终信任”

您可能需要重新启动 Chrome 才能使证书完全受信任(网址栏中的图标变为快乐的绿色锁)。

【讨论】:

【参考方案3】:

值得一提的是,还有另一种情况会产生绝对外观完全相同的结果:

如果您在等待请求返回(即通过承诺)时将浏览器重新定位到不同的 URL (window.location ..),则将提交 OPTIONS 请求,但随后的响应 (POST/GET/*)将被取消(自然..)

是的..当然..如果你这样做是一个错误..但它可能看起来完全一样,并且在错误的地方寻找几个小时。 考虑这样的代码:

makeAjaxCallThatReturnsAPromise.then(
    function ()  // doSomething ,
    function ()  // doSomethingElse 
);
location.replace('http://some.where/');

【讨论】:

我得说,这个 CORS 失败是一个真正的沉睡者。它真的从来没有被写过,在阅读本文之前,我花了很多时间在上面。由于我们当然无法控制的时间问题,这就是问题所在。我在 ajax POST 之前更改了 window.location 页面,但一直失败。在阅读了这个答案后,我将 window.location 语句移到了成功:我的 $.post 语句的代码中,它起作用了。如果所有其他内容都已验证,则必须检查!非常有帮助! +1

以上是关于为啥 Chrome 会取消 CORS OPTION 请求的主要内容,如果未能解决你的问题,请参考以下文章

在Chrome中取消了飞行前OPTIONS请求(已支持CORS)

为啥在 Firefox 中向 google Drive Sheet 发出的这个 CORS 请求会失败? (在 Chrome 中工作)

在 Chrome 中取消 Pre-Flight OPTIONS 请求(已经支持 CORS)

Chrome:CORS HTTPS 请求的 GET 请求已取消

为啥经过身份验证的 CORS 请求的预检 OPTIONS 请求在 Chrome 中有效,但在 Firefox 中无效?

为啥 Chrome 会删除 localhost:80 的端口号?