Safari不会跨不同域缓存资源

时间:2014-07-07 17:45:57

标签: caching safari browser-cache cdn google-cdn

假设我们有几个不同的网站:website1.com,website2.com,website3.com。我们在所有这些上使用jQuery,并将其包含在像googleapis.com这样的CDN中。浏览器的预期行为是将其缓存一次并将其用于所有其他网站。 Chrome似乎是这样做的,但Safari会为每个域下载jQuery。

实施例

  1. 使用以下给定的JS代码在Chrome中打开nytimes.combbc.comdw.de
  2. 在第一个网站上添加jQuery,然后查看DevTools的Network选项卡。它会说它有jQuery。
  3. 现在打开任何其他网站并再次添加jQuery - 答案将是“来自缓存”。
  4. 然而,Safari会说它正在为每个域加载jQuery,但是尝试在其中一个域上打开任何网页并再次附加脚本 - 你会看到现在它说它从缓存中获得了jQuery。所以看起来它缓存了域的数据,即使它已经从另一个域的确切URL下载了资源。

    这个假设是否正确,如果是,如何解决?

    您可以复制/粘贴的代码:

    setTimeout(function() {
        var SCRIPT_SRC = '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js';
    
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = SCRIPT_SRC;
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    }, 0);
    

    UPD:用静态图像测试它。

    test.com,test2.com和test3.com有<img src="http://image.com/image.jpg" />。在除Safari之外的所有浏览器中,日志仅显示一个 - 首先 - 请求图像。 Safari获取每个新域(但不是子域)的图像。

3 个答案:

答案 0 :(得分:3)

我也注意到了这一点,我怀疑是出于隐私原因。

默认情况下,Safari阻止third-party cookies。第三方Cookie是b.com上为a.com请求的资源设置的Cookie。例如,这可以用于跨域跟踪人员。您可以在b.coma.com请求的c.com上添加脚本。 b.com可以根据第三方Cookie在此脚本中插入唯一的客户ID,以便a.comc.com可以跟踪这是同一个人。

Safari会阻止此行为。如果b.coma.com请求的资源设置了Cookie,则Safari会将该Cookie设置为只有b.com才会发送给a.com以获取b.com的更多请求。对于c.com的请求,我们不会将其发送至Etag

现在输入缓存,特别是Etag标头。 Etag是一个任意字符串(通常是文件的散列),可用于确定所请求的资源自上次请求之后是否已更改。这通常是件好事。如果整个文件没有更改,它会保存重新发送的文件。

但是,由于b.com任意字符串, <div class="col-sm-9"> <select name="id_jenis_surat" class="form-control"> <option></option> @foreach($jenis_surat as $js) <option value="{{ $js->id_jenis_surat }}" @if($combobox_value_from_database==$js->id_jenis_surat) selected="selected" @endif> {{ $js->jenis_surat }} </option> @endforeach </select> 可以将其设置为包含客户端ID。这称为Etag tracking。它允许以几乎与cookie完全相同的方式跨域跟踪人。

摘要:通过不跨域共享缓存,Safari可以保护您免受跨域Etag跟踪。

答案 1 :(得分:0)

您可以尝试使用XMLHTTPRequest,而不是简单地添加DOM元素。它允许您定义自定义标头 - 其中一个是Cache-Control

给它一个镜头,它应该覆盖浏览器级别的任何内容:

(function () {

    var newRequest = function() {
        return (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject( 'MsXml2.XmlHttp' );
    }

    var loadScript = function(url) {

        var http = new newRequest();

        http.onReadyStateChange = function() {
            if (http.readyState === 4) {
                if (http.status === 200 || http.status === 304) {
                    appendToPage(http.responseText);
                }
            }
        }

        // This is where you set your cache
        http.setRequestHeader( 'Cache-Control', 'max-age=0' )// <-- change this to a value larger than 0

        http.open('GET', url, true);
        http.send(null);
    }

    var appendToPage = function(source) {

        if (source === null) return false;

        var head = document.getElementsByTagName('head')[0];

        var script = document.createElement('script');
            script.language = 'javascript';
            script.type  = 'text/javascript';
            script.defer = true;
            script.text  = source;

        head.appendChild(script);
    }

    loadScript( '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js' );
})();

注意:Safari过去遇到了一些缓存问题。但是,根据我的理解,这主要是关于提供过时的内容 - 而不是相反。

答案 2 :(得分:-1)

以下是一些建议:

  1. 您是否检查过&#34;禁用缓存&#34;选项被禁用?
  2. 您是否在网络开发面板中查找HTTP状态代码?
  3. 您是否尝试使用WireShark等工具捕获流量?
  4. 最好的问候。