写在前面: 如果未来的某一天,你再次发现明明已经从存储桶里永久删除的图片,竟然还能在浏览器里正常访问,甚至 Cloudflare 缓存怎么清都清不掉。 请冷静,不要怀疑 CDN 出了 Bug,也不要觉得遇到了灵异事件。 回来看这篇笔记,凶手就是当初那个“过于贴心”的开源项目代码。
👻 灵异现象:图片“复活”了
事情的起因很简单:我基于开源项目 MarSeventh/CloudFlare-ImgBed 搭建了自己的图床,后端存储使用的是 Cloudflare R2。
某天我决定重构图床,于是清空了 R2 存储桶,甚至删除了整个项目重新部署。按理说,旧的图片链接应该全部变红(404 Not Found)。
然而,诡异的事情发生了:
- 访问旧图片链接:图片依然正常加载,毫发无损。
- 检查 R2 桶:里面空空如也,根本没有这个文件。
- 检查 KV 数据库:也是空的,没有记录。
- CDN 缓存:我在 Cloudflare 后台点击了
Purge All Cache(清除所有缓存)。 - 结果:清除缓存后,第一次访问短暂变慢(回源),紧接着控制台再次显示
CF-Cache-Status: HIT。
一张在物理层面已经被“销毁”的图片,为什么会像幽灵一样,每次清除缓存后都能原地复活?
1. 项目的前世今生
CloudFlare-ImgBed 这个项目,最早其实是基于 Telegra.ph(Telegram 的匿名发布平台)做的。
- 早期逻辑:用户上传 -> Worker 转发给 Telegra.ph -> 返回 Telegra.ph 的图片链接。
- 后期升级:Cloudflare 推出了 R2 存储,作者为了稳定性,增加了 R2 支持,把 R2 作为首选存储。
2. “Telegra.ph禁用免费的接口
以前上传到 Telegraph 的图片不受影响,现在无法再白嫖了,为了避免已经上传的图片无法使用,代码底层逻辑会继续try get Telegra.ph的图片。
3. 真相大白
这就是“缓存复活”的完整链条:
我点了“清除缓存” -> 边缘节点缓存清空。
我访问图片 -> 边缘节点发现没缓存 -> 请求回源给 Worker。
Worker 去 R2 查 -> 发现文件没了(因为我删了)。
Worker 触发兜底逻辑 -> 偷偷去
telegra.ph请求同名文件。由于 Telegra.ph 的图片是永久存储且无法删除的 -> Worker 拿到了图片!
Worker 把图片传回给边缘节点 -> 边缘节点重新缓存该图片 -> 用户看到图片。
既然找到了原因,解决办法就很简单。我不希望我的图床和不可控的 Telegra.ph 藕断丝连,我要它变成一个纯粹的 R2 图床。
修改 Worker 代码:
找到类似 fetch('https://telegra.ph/file/' + ...) 的代码段,将其删除或注释,改为直接返回 404。
JavaScript
| |
修改部署后,再次清除 CDN 缓存。这一次,幽灵图片终于彻底消失了,返回了令我安心的 404 Not Found。