自从前几天 Otomad Site 网站开业,群友们就开始高强度水贴,其中也有一些群友开始玩起了网站的 Bubble Game,也有一些朋友开始了疯狂的逆向和发包工作。
在玩的过程中,有人注意到了一个奇怪的问题:排行榜没有实时刷新。当完成一次能刷新排行榜的游戏以后,排行榜并没有及时刷新,而在等了几个小时以后,排行榜才更新。因此,好奇的我开始研究这是什么问题。
从源代码出发
Otomad Site 是基于 MissKey 部署的,而且我们也能在里面找到 Bubble Game 的 源代码。这里主要是后端的源代码,前端和游戏引擎也在这个仓库,但是和这次的探讨无关。
这里后端没有对游戏结果做任何校验,暂且按下不表,但是我们可以在源代码看到它的缓存逻辑。在 ranking.ts,声明了缓存:
export const meta = {
allowGet: true,
cacheSec: 60,
// --snip--
} as const;
而这个 cacheSec 会在对应的文件,设置为 Cache-Control 头的 max-age:
this.call(endpoint, user, app, body, null, request).then((res) => {
if (request.method === 'GET' && endpoint.meta.cacheSec && !token && !user) {
reply.header('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`);
}
this.send(reply, res);
}).catch((err: ApiError) => {
this.#sendApiError(reply, err);
});
这里的头会提醒浏览器,让浏览器对这个 API 进行缓存,以减小服务器侧的负担。
然而,当我们实际发包时,却发现这个头被改了:
❯ curl "https://otomad.site/api/bubble-game/ranking?gameMode=normal" -v &| grep cache-control -C 3
< server: cloudflare
< strict-transport-security: max-age=15552000; preload
< access-control-allow-origin: *
< cache-control: public, max-age=14400
< x-cache: EXPIRED
< accept-ranges: bytes
< age: 53
这可以解释为什么它要等几个小时(也就是 4 个小时)才会更新排行榜:因为浏览器知道要缓存 14400 秒,在这段时间内,它就不会再重新请求新的排行榜。
但是,为什么这个头会被改掉呢?我把视角转到了 Cloudflare。
Cloudflare 的文档
不难注意到,Otomad Site 是用 Cloudflare 做的全球加速 CDN 的。我怀疑这很可能是 Cloudflare 改的值。最终,我在 Cloudflare 文档中找到了对应的部分:
The Browser Cache TTL sets the expiration for resources cached in a visitor’s browser. By default, Cloudflare honors the cache expiration set in your Expires and Cache-Control headers but overrides those headers if:
- The value of the Expires or Cache-Control header from the origin web server is less than the Browser Cache TTL Cloudflare setting.
- The origin web server does not send a Cache-Control or an Expires header.
Unless specifically set in a cache rule, Cloudflare does not override or insert Cache-Control headers if you set Browser Cache TTL to Respect Existing Headers.
也就是说,Cloudflare 会自动添加 Browser Cache TTL 为一个固定的值。在原文下面有表格,这个值被设定为了 4 小时。要更改这一选项,我们要在 Cloudflare 上更改相关设置。
总结
Cloudflare 干的。以后要多读文档啊!