使用 Cloudflare Workers 和 KV 存储做图片反向代理

需求背景

在国内,有很多互联网的服务用起来并不爽,很多时候会遇到网站打开了,图片死活加载不出来或者加载到一半就不加载了。比如 Gravatar 的图像服务,又比如 Fanza 的图片。在终端不用 Proxy 的前提下,解决这个问题,需要做一个反向代理来实现。

为什么用 Cloudflare

  • 我的域名在 Cloudflare
  • Cloudflare Workers 有免费额度
  • Cloudflare KV 有免费额度
  • Cloudflare 全球都有服务器,比一般自己搭建的牛逼多了
  • 我不想自己开 nginx 实现

综上,这就是为什么使用 Cloudflare 的 Workers 和 KV 服务来实现了。

流程逻辑

flow

具体步骤

准备动作

  • 准备一个能够正常访问的域名;
  • 能够正常访问 Cloudflare 的网络条件
  • Cloudflare 账号
  • gooreplacer 插件

开启 KV

操作步骤以英文界面为准,因为 Cloudflare 的中文翻译太垃圾了。

创建 namespaces

  • 点击 “Workers & Pages”
  • 点击 “KV”
  • 点击 “Create a namespaces”
    KV_0001
  • 在 “Namespace Name” 输入 “RVCACHE” (RVCACHE 可自己改成想要的名字)
  • 点击 “Add”
    KV_0002

创建 Workers

  • 点击 “Workers & Pages”
  • 点击 “Overview”
  • 点击 “Create”
    WK_0001
  • 点击 “Create Worker”
    WK_0002
  • “Name your project” 输入你的项目名字
  • 点击 “SAVE”
  • 点击 “Finish”
    WK_0003

Workers 绑定 KV

  • 点击创建的 Workers
  • 点击 “Setting”
  • 点击 “Variables”
  • 找到 “KV Namespace Bindings”
  • 点击 “Add binding”
    BD_0001
  • “Variable name” 输入 “RVCACHE”
  • “KV Namespace” 点击 “select” 选择刚才创建的 “RVCACHE”
  • 点击 “Deploy”
    BD_0002

编写代码

  • 点击 “Edit Code”
    ED_0001
  • 粘贴以下代码
    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”
    ED_0002
  • 点击 “Save and deploy”
    ED_0003

Workers 绑定域名

  • 点击 “Setting”
  • 点击 “Triggers”
  • “Custom Domains” 点击 “Add Custom Domain”
  • “Domain” 输入自己的域名
  • 点击 “Add Custom Domain”
    AD_0001

浏览器插件配置

其他备注

  1. 多路径支持,参照写法多加一行即可;
  2. 上述代码是使用 OpenAI 的 ChatGPT 写的。

使用 Cloudflare Workers 和 KV 存储做图片反向代理
https://www.saru.im/posts/43261.html
作者
Mark_Deng
發布於
2024年6月25日
許可協議