因缺失 Vary: Origin 导致的缓存错乱

这些天把字体文件移动到 CDN 上时,遇到浏览器缓存异常的问题。
有两个站点分别是 https://powerfulyang.comhttps://qa.powerfulyang.com ,都引用了跨域资源 https://static.powerfulyang.com/fonts/zpix.woff 文件。
但是发现访问 https://powerfulyang.com 之后再访问 https://qa.powerfulyang.com 会发现请求字体文件时报跨域错误,即 response header 中 Access-Control-Allow-Origin 的值是访问 https://powerfulyang.com 留下的缓存为 https://powerfulyang.com 。其中原因经查阅,了解到主要是 response header 中缺少了 Vary: Origin 这一部分,导致缓存没有按 Origin 分别缓存,只缓存了一份导致的问题。

浏览器缓存机制

Relate to https://zhuanlan.zhihu.com/p/38972475

由于浏览器里的缓存是以 URL 为 key 的,一个 URL 对应一个缓存,但是当浏览器访问了两个 URL 相同但 CORS 响应头不相同的资源。
比如在同一个浏览器下,先打开了 https://foo.taobao.com 上的一个页面,访问了我们的资源,这个资源被浏览器缓存了下来,和资源内容一起缓存的还有 Access-Control-Allow-Origin: https://foo.taobao.com 响应头。这时又打开 https://bar.taobao.com 上的一个页面,这个页面也要访问那个资源,这时它会读取本地缓存,读到的 Access-Control-Allow-Origin 头是缓存下的 https://foo.taobao.com 而不是自己想要的 https://bar.taobao.com ,这时就报跨域错误了。

使用 Vary: Origin 让同一个 URL 有多份缓存

有一个 HTTP 响应头叫 Vary,vary 这个单词的意思是“变化”、“不同”的意思,Vary 响应头就是让同一个 URL 根据某个请求头的不同而使用不同的缓存。比如常见的 Vary: Accept-Encoding 表示客户端要根据 Accept-Encoding 请求头的不同而使用不同的缓存,比如 gizp 的缓存一份,未压缩的缓存为另一份。

https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches However, if Access-Control-Allow-Origin is set to * or a static origin for a particular resource, then configure the server to always send Access-Control-Allow-Origin in responses for the resource — for non-CORS requests as well as CORS requests — and do not use Vary.

总结:最终选择了懒惰的方法,直接设置 Access-Control-Allow-Origin: * 来解决不同 Origin 访问报跨域错误的问题。