使用 Cloudflare Workers 和 KV 存储做图片反向代理
需求背景
在国内,有很多互联网的服务用起来并不爽,很多时候会遇到网站打开了,图片死活加载不出来或者加载到一半就不加载了。比如 Gravatar 的图像服务,又比如 Fanza 的图片。在终端不用 Proxy 的前提下,解决这个问题,需要做一个反向代理来实现。
为什么用 Cloudflare
- 我的域名在 Cloudflare
- Cloudflare Workers 有免费额度
- Cloudflare KV 有免费额度
- Cloudflare 全球都有服务器,比一般自己搭建的牛逼多了
- 我不想自己开 nginx 实现
综上,这就是为什么使用 Cloudflare 的 Workers 和 KV 服务来实现了。
流程逻辑
具体步骤
准备动作
- 准备一个能够正常访问的域名;
- 能够正常访问 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”
- 粘贴以下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64// 定义路径映射
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.html