为什么Chrome取消CORS OPTION请求



在我的应用程序我创建AJAX请求从HTTP到HTTPS。这意味着我需要CORS。所以我给jQuery添加了一些header和params。Ajax并测试它。在Firefox中一切正常,但在Chrome中不是。Chrome "kill"每个预先发送的请求(OPTIONS)。

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杀死这个请求吗?

可能您的https服务器有不受信任的证书。如果是,请先尝试用浏览器访问该URL,然后接受不受信任的连接。

接受证书并不总能解决这个问题。如果您使用自签名证书,即使您首先接受它,Chrome仍然会在某些情况下取消您的预飞行选项请求。自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/):

  1. 在地址栏中,点击带有x的小锁,这将弹出一个小信息屏幕。
  2. 点击"证书信息"按钮
  3. 单击并拖动证书图像到您的桌面打开的查找器窗口(它似乎不喜欢拖到桌面)
  4. 双击创建的文件。这将打开Keychain Access实用程序。输入您的密码解锁。
  5. 请确保将证书添加到系统密钥链中,而不是登录密钥链中。点击"始终信任",即使这似乎没有做任何事情。
  6. 添加完成后双击。您可能需要重新验证。
  7. 展开"Trust"部分。"当使用此证书时,"设置为"始终信任"

您可能需要重新启动Chrome的证书是完全可信的(图标更改为一个快乐的绿色锁定在url栏)。

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

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

是的. .当然……如果你那样做,这是一个bug。但它可能看起来是一样的,并花费数小时在错误的地方寻找。考虑这样的代码:

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

最新更新