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

需求背景

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

为什么用 Cloudflare

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

流程逻辑

flow

具体步骤

准备动作

开启 KV

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

创建 namespaces

创建 Workers

Workers 绑定 KV

编写代码

JS
// 定义路径映射
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));
});
点击展开查看更多

Workers 绑定域名

浏览器插件配置

其他备注

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

版权声明

作者: Mark_Deng

链接: https://www.saru.im/posts/43261/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

评论

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键