github cloudflare workers

github cloudflare workers

·

基于 CloudFlare 搭建 Github 镜像站 | nil's blog !


基于 CloudFlare 搭建 Github 镜像站


 更新时间: Invalid Date | 


 总字数: 1267 字 | 


 阅读时长: 8 分钟

前言

Github 作为我们日常开发的必备网站,经常会遇到访问比较慢或完全无法访问的情况,虽然已经有不少代理项目可以实现加速访问,但还是有很多人不知道如何去操作,本文就通过 CloudFlare Workers 来实现 Github 访问加速。

准备工作

需要准备一个可以添加解析的域名,新注册域名,厂商会要求实名后才允许进行解析。

注册 CloudFlare 账号

访问 https://dash.cloudflare.com/sign-up 进行注册。

找到注册邮箱中的验证邮件,访问验证链接会跳转至如下页面,然后点击 添加网站或应用程序 。

配置 Workers 服务

添加 Workers

在工作台左侧菜单中,点击 Workers 和 Pages 。

进入如下页面,点击 创建 Worker ,使用默认模板创建即可。

为了方便区分,输入自定义 Workers 子域名称 ,然后点击 部署 。

跳转如下说明部署成功,点击 编辑代码 。

配置代理代码

接下来,将如下 Github 加速代码全部复制,替换掉 worker.js 所有内容,然后 保存并部署,弹窗继续点击 保存并部署。

将如下代码全部复制,替换掉 worker.js 所有内容。
let domainMaps = {};
let reverseDomainMaps = {};
const index = {
  async fetch(request, env, _ctx) {
    const needCancel = await needCancelRequest(request);
    if (needCancel)
      return new Response("", {status: 204});
    const url = new URL(request.url);
    const {domain, subdomain} = getDomainAndSubdomain(request);
    if (url.pathname === "/robots.txt")
      return new Response("User-agent: *\nDisallow: /", {status: 200});
    domainMaps = {
      [`hub.${domain}`]: "github.com",
      [`assets.${domain}`]: "github.githubassets.com",
      [`raw.${domain}`]: "raw.githubusercontent.com",
      [`download.${domain}`]: "codeload.github.com",
      [`object.${domain}`]: "objects.githubusercontent.com",
      [`media.${domain}`]: "media.githubusercontent.com",
      [`gist.${domain}`]: "gist.github.com"
    };
    reverseDomainMaps = Object.fromEntries(Object.entries(domainMaps).map((arr) => arr.reverse()));
    if (url.host in domainMaps) {
      url.host = domainMaps[url.host];
      if (url.port !== "80" && url.port !== "443")
        url.port = url.protocol === "https:" ? "443" : "80";
      const newRequest = getNewRequest(url, request);
      return proxy(url, newRequest);
    }
    return new Response(`Unsupported domain ${subdomain ? `${subdomain}.` : ""}${domain}`, {
      status: 200,
      headers: {"content-type": "text/plain;charset=utf-8", "git-hash": env.GIT_HASH}
    });
  }
};

function getDomainAndSubdomain(request) {
  const url = new URL(request.url);
  const hostArr = url.host.split(".");
  let subdomain = "";
  let domain = "";
  if (hostArr.length > 2) {
    subdomain = hostArr[0];
    domain = hostArr.slice(1).join(".");
  } else if (hostArr.length === 2) {
    subdomain = hostArr[1].match(/^localhost(:\d+)?$/) ? hostArr[0] : "";
    domain = hostArr[1].match(/^localhost(:\d+)?$/) ? hostArr[1] : hostArr.join(".");
  } else {
    domain = hostArr.join(".");
  }
  return {domain, subdomain};
}

async function needCancelRequest(request, matches = []) {
  const url = new URL(request.url);
  matches = matches.length ? matches : [
    "/favicon.",
    "/sw.js"
  ];
  return matches.some((match) => url.pathname.includes(match));
}

function getNewRequest(url, request) {
  const headers = new Headers(request.headers);
  headers.set("reason", "mirror of China");
  const newRequestInit = {redirect: "manual", headers};
  return new Request(url.toString(), new Request(request, newRequestInit));
}

async function proxy(url, request, env) {
  try {
    const res = await fetch(url.toString(), request);
    const headers = res.headers;
    const newHeaders = new Headers(headers);
    const status = res.status;
    if (newHeaders.has("location")) {
      const loc = newHeaders.get("location");
      if (loc) {
        try {
          const locUrl = new URL(loc);
          if (locUrl.host in reverseDomainMaps) {
            locUrl.host = reverseDomainMaps[locUrl.host];
            newHeaders.set("location", locUrl.toString());
          }
        } catch (e) {
          console.error(e);
        }
      }
    }
    newHeaders.set("access-control-expose-headers", "*");
    newHeaders.set("access-control-allow-origin", "*");
    newHeaders.delete("content-security-policy");
    newHeaders.delete("content-security-policy-report-only");
    newHeaders.delete("clear-site-data");
    if (res.headers.get("content-type")?.indexOf("text/html") !== -1) {
      const body = await res.text();
      const regAll = new RegExp(Object.keys(reverseDomainMaps).map((r) => `(https?://${r})`).join("|"), "g");
      const newBody = body.replace(regAll, (match) => {
        return match.replace(/^(https?:\/\/)(.*?)$/g, (m, p1, p2) => {
          return reverseDomainMaps[p2] ? `${p1}${reverseDomainMaps[p2]}` : m;
        });
      }).replace(/integrity=\".*?\"/g, "");
      return new Response(newBody, {status, headers: newHeaders});
    }
    return new Response(res.body, {status, headers: newHeaders});
  } catch (e) {
    return new Response(e.message, {status: 500});
  }
}

export {index as default};

配置域名

服务默认提供域名 workers.dev 无法在国内直接访问,所以需要添加自定义域名来进行访问。

添加域名

点击控制台顶部 添加站点 。

进入如下页面,输入需要绑定的域名,然后再点击继续。

配置域名解析

跳转至如下概述页面,然后在域名服务商管理平台将 DNS 服务器修改为 CloudFlare 所提供的。

其他未列出域名服务商,DNS 服务器设置大同小异,可参考官方文档或自行百度即可。

在域名服务商平台配置完 DNS 服务器后,需要耐心等待一段时间,当添加的站点激活时,注册邮箱会收到如下通知邮件。

当站点激活后,域名状态则变为有效。

服务绑定

接下来,继续点击 Workers 和 Pages 进入服务页面,然后点击服务名称,进入服务详情。

进入设置 - 变量标签页,添加变量,名称为固定值 DOMAIN,值为绑定的域名,点击加密,保存并部署。

接下来进入触发器标签页,添加自定义域和路由。

代理列表如下:

ProxyHostnamehub.cnmirror.ccgithub.comraw.cnmirror.ccraw.githubusercontent.comassets.cnmirror.ccgithub.githubassets.comdownload.cnmirror.cccodeload.github.comobject.cnmirror.ccobjects.githubusercontent.commedia.cnmirror.ccmedia.githubusercontent.comgist.cnmirror.ccgist.github.com

将如上代理添加至自定义域中,配置好路由,最终如下:

至此,所有内容已经配置完成,接下来就可以正常使用了,现在打开 https://hub.cnmirror.cc 就可以访问 Github 了,建议不要登录 Github 账号使用。



Pager

上一篇

正则表达式说明