如何使用 Github Private Repo 作为图床并且不被科学

X1a0t,3 min read

前序

Github 作为图床两大缺点: 链接会被科学,无法被更多人看到。并且 存储在公开的仓库有隐私问题。但是稳定,免费的优点实在让这俩个缺点瑕不掩瑜。而且有一些类似 PicGO 这样的开源项目集成了 Github 仓库作为图床,可以直接从剪切板上传图片到 repo。

Github 图床这么好用,这两个缺点一定要存在吗?我做了一些尝试,发现这两个问题是可以被解决的。废话不多说,直接上解决方案。

  1. 首先图片被科学是因为域名 raw.githubusercontent.com 脏了。我们只要买一个干净的域名,把任何 raw.githubusercontent.com/<user>/<repo>/<branch>/path/to/imagemy.image.proxy.com/<user>/<repo>/<branch>/path/to/image 代替,并且域名把 my.image.proxy.com CNAME 到 raw.githubusercontent.com,就可以了。

  2. 公开的仓库有隐私问题,我们可以把图片放在 Github Private 仓库。为了 Private 仓库内的内容可以被访问,需要在请求头加上 Authorization,就像这样:

curl -H 'Authorization: token INSERTACCESSTOKENHERE' \
  -O \
  -L https://raw.githubusercontent.com/repos/owner/repo/contents/path

但问题是用户用浏览器加载图片,不可能自己加上 Authorization 请求头,并且这个 Auth Token 不可能公开,不然仓库 Private 就没意义了。为了解决这个问题我们可以搞一层很薄的代理,把请求转发到 Github Private 仓库,带上 Authorization 请求头。以 CloudFlare Worker 为例,推荐针对图床仓库 创建一个只读 token (opens in a new tab),配到 Worker 的 Secret 里:

export default {
  async fetch(request, env) {
    try {
      const GITHUB_IMAGE_HOST = "raw.githubusercontent.com";
      const GITHUB_TOKEN = env.repo_read_only_token;
 
      if (!GITHUB_TOKEN) {
        console.error("GitHub token not configured");
        return new Response("Error: GitHub token not configured", {
          status: 500,
        });
      }
 
      const oldUrl = new URL(request.url);
 
      if (oldUrl.pathname === "/") {
        return new Response(`https://${oldUrl.hostname}/v1`, { status: 200 });
      }
 
      const newUrl = new URL(request.url);
      newUrl.hostname = GITHUB_IMAGE_HOST;
 
      const newHeaders = new Headers(request.headers);
      newHeaders.set("Authorization", `token ${GITHUB_TOKEN}`);
      newHeaders.set("Accept", "application/vnd.github.v3.raw");
 
      const modifiedRequest = new Request(newUrl, {
        method: request.method,
        headers: newHeaders,
        body: request.body,
      });
 
      const response = await fetch(modifiedRequest);
 
      if (!response.ok) {
        console.error(
          `GitHub API error: ${response.status} ${response.statusText}`
        );
        return response;
      }
 
      return response;
    } catch (e) {
      console.error(e);
      return new Response(e.stack, { status: 500 });
    }
  },
};

配好之后,效果就像这样:

CC BY-NC 4.0 2025 © Powered by Nextra.