Safari doesn't cache resources across different domains

browser-cache, caching, cdn, google-cdn, safari

Solution

I've noticed this too, and I suspect it is for privacy reasons.

By default, Safari blocks third-party cookies. A third party cookie is a cookie set on `b.com` on for a resource that is requested by `a.com`. This can be used, for example, to track people across domains. You can have a script on `b.com` that is requested by `a.com` and by `c.com`. `b.com` can insert a unique client ID into this script based on a third-party cookie, so that `a.com` and `c.com` can track that this is the same person.

Safari blocks this behavior. If `b.com` sets a cookie for a resource requested by `a.com`, Safari will box that cookie so it is only sent to `b.com` for more requests by `a.com`. It will not be sent to `b.com` for requests by `c.com`.

Now enter caching and specifically the `Etag` header. An `Etag` is an arbitrary string (usually a hash of the file) that can be used to determine if the requested resource has changed since the person requested it last. This is normally a good thing. It saves re-sending the entire file if it is has not changed.

However, because an `Etag` is an arbitrary string, `b.com` can set it to include a client ID. This is called Etag tracking. It allows tracking a person across domains in almost exactly the same way as cookies do.

Summary: By not sharing the cache across domains, Safari protects you from cross-domain Etag tracking.

Problem

Let’s say we have several different websites: website1.com, website2.com, website3.com. We use jQuery on all of them and include it from CDN like googleapis.com. The expected behavior from a browser would be to cache it once and use it for all other websites. Chrome seems to do it, but Safari downloads jQuery for every domain. Example - With the given JS code below open nytimes.com, bbc.com and dw.de in Chrome. - Append jQuery on the first website and look at the Network tab of your DevTools. It will say that it got jQuery. - Now open any other website and append jQuery again — the answer will be “from cache”. However, Safari will say it’s loading jQuery for every domain, but try to open any webpage on one of the domains and append the script again — you will see that now it says it got jQuery from cache. So it looks like it caches data for a domain, even if it has already downloaded a resource from the exact URL for another domain. Is this assumption correct and if so, how to fix it? Code you can copy/paste: ``` 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: Tested it with a static image. test.com, test2.com and test3.com have `<img src="http://image.com/image.jpg" />`. In all browsers except for Safari access log shows only one — first — request for the image. Safari gets the image for every new domain (but not a subdomain).

Original source