Mika Pikazo
879 字
4 分钟
使用 Cloudflare Workers 和 KV 存储做图片反向代理
CAUTIONCloudflare 已经更新相关 ToS,本文介绍的内容会违反 ToS 限制。有可能导致封号,请勿参考。
需求背景
在国内,有很多互联网的服务用起来并不爽,很多时候会遇到网站打开了,图片死活加载不出来或者加载到一半就不加载了。比如 Gravatar 的图像服务,又比如 Fanza 的图片。在终端不用 Proxy 的前提下,解决这个问题,需要做一个反向代理来实现。
为什么用 Cloudflare
- 我的域名在 Cloudflare
- Cloudflare Workers 有免费额度
- Cloudflare KV 有免费额度
- Cloudflare 全球都有服务器,比一般自己搭建的牛逼多了
- 我不想自己开 nginx 实现
综上,这就是为什么使用 Cloudflare 的 Workers 和 KV 服务来实现了。
流程逻辑
graph TD
A([浏览器请求]) --> B[插件匹配清单]
B --> C{是否匹配规则?}
C -- yes --> D[插件替换请求路径为 Cloudflare 绑定域名]
D --> E[Cloudflare Workers 反代并缓存]
C -- no --> F[不操作]
E --> G([返回信息])
F --> G
具体步骤
准备动作
- 准备一个能够正常访问的域名;
- 能够正常访问 Cloudflare 的网络条件
- Cloudflare 账号
- gooreplacer 插件
开启 KV
操作步骤以英文界面为准,因为 Cloudflare 的中文翻译太垃圾了。
创建 namespaces
- 点击 “Workers & Pages”
- 点击 “KV”
- 点击 “Create a namespaces”

- 在 “Namespace Name” 输入 “RVCACHE” (RVCACHE 可自己改成想要的名字)
- 点击 “Add”

创建 Workers
- 点击 “Workers & Pages”
- 点击 “Overview”
- 点击 “Create”

- 点击 “Create Worker”

- “Name your project” 输入你的项目名字
- 点击 “SAVE”
- 点击 “Finish”

Workers 绑定 KV
- 点击创建的 Workers
- 点击 “Setting”
- 点击 “Variables”
- 找到 “KV Namespace Bindings”
- 点击 “Add binding”

- “Variable name” 输入 “RVCACHE”
- “KV Namespace” 点击 “select” 选择刚才创建的 “RVCACHE”
- 点击 “Deploy”

编写代码
- 点击 “Edit Code”

- 粘贴以下代码
// 定义路径映射const PATH_MAP = { "/gravatar": "https://secure.gravatar.com",};
async function handleRequest(request) { const url = new URL(request.url); const pathParts = url.pathname.split('/'); const route = `/${pathParts[1]}`;
const originBase = PATH_MAP[route];
if (!originBase) { // 如果请求的路径不在映射表中,返回 404 return new Response('Route not mapped', { status: 404 }); }
// 构建 cacheKey 和 originUrl const cacheKey = `${route}${url.pathname.replace(route, '')}`; const originUrl = `${originBase}${url.pathname.replace(route, '')}`;
// 从 KV 中检查缓存 const cache = await REVERSE_CACHE.get(cacheKey, { type: 'arrayBuffer' });
if (cache) { // 返回缓存的响应 return new Response(cache, { headers: { 'Content-Type': 'application/octet-stream', 'X-Worker-Cache': 'HIT' } }); }
// 如果缓存中没有,则从 origin 获取 const response = await fetch(originUrl);
if (response.ok) { const contentType = response.headers.get('Content-Type');
// 检查是否为常见图片类型 if (contentType && (contentType.includes('image/jpeg') || contentType.includes('image/png') || contentType.includes('image/gif'))) { const responseData = await response.arrayBuffer(); // 缓存响应 await REVERSE_CACHE.put(cacheKey, responseData, { expirationTtl: 86400 }); // 缓存一天
return new Response(responseData, { headers: { 'Content-Type': contentType, 'X-Worker-Cache': 'MISS' } }); } else { // 不是常见图片类型,不缓存,直接返回 return response; } } else { return new Response('Not found', { status: 404 }); }}
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request));});- 点击 “Deploy”

- 点击 “Save and deploy”

Workers 绑定域名
- 点击 “Setting”
- 点击 “Triggers”
- “Custom Domains” 点击 “Add Custom Domain”
- “Domain” 输入自己的域名
- 点击 “Add Custom Domain”

浏览器插件配置
- 点击”新增”

- “匹配模式” 输入需要被反代的域名,以 Gravatar 为例就是 “https://secure.gravatar.com”
- “匹配类型” 保持不变,选择通配符
- “目标地址” 输入 Cloudflare Workers 的域名,如 www.example.com,结合
PATH_MAP中定义的目录,构造后的地址就是 “https://www.example.com/gravatar/” - 点击 “提交”
其他备注
- 多路径支持,参照写法多加一行即可;
- 上述代码是使用 OpenAI 的 ChatGPT 写的。
使用 Cloudflare Workers 和 KV 存储做图片反向代理
https://www.saru.im/posts/43261/