前言
检查更新通常是一个软件必备的功能,通过 Github Api 可以比较方便的实现更新检查,但是国内的访问比较困难,通过 Cloudflare 加速就显得很有必要了。
实现过程
Github 中的资源分为3块
-
Api
比如https://api.github.com/repos/chr233/asfenhance/releases
-
仓库中的静态文件
比如http://raw.githubusercontent.com/chr233/PureNGA/refs/heads/main/.github/aifadian.png
-
Release 中的文件
比如https://github.com/chr233/ASFEnhance/releases/download/2.3.12.0/ASFEnhance.zip
Worker 脚本如下
有两种思路, 一种是3种资源使用3个 Worker 处理,这样最简单, 还有一种是在一个 Worker 中一起处理
方案一, 3个 Worker
- Api
Github 需要设置 ApiToken
, 在 Worker 里设置 GH_TOKEN
为自己的 ApiToken
就行
export default {
async fetch(request, env, ctx) {
const { GH_TOKEN } = env;
const { host, pathname } = new URL(request.url);
if (pathname === '/') {
return new Response(`this is a mirror of https://api.github.com\r\nsuch as https://api.github.com/repos/chr233/purenga -> https://${host}/purenga`, { status: 200 });
}
// GitHub 仓库文件地址
const github_host = "api.github.com/repos/chr233";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host, github_host);
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${GH_TOKEN}`,
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
}
});
const target_host = "https://github.com/chr233";
const mirror_host = "https://download.chrxw.com";
const body = await response.text();
const new_body = body.replaceAll(target_host, mirror_host)
return new Response(new_body, response);
}
}
- Raw
export default {
async fetch(request, env, ctx) {
const { host, pathname } = new URL(request.url);
if (pathname === '/') {
return new Response(`this is a mirror of https://raw.githubusercontent.com\r\nsuch as https://raw.githubusercontent.com/chr233/purenga -> https://${host}/purenga`, { status: 200 });
}
// GitHub 仓库文件地址
const github_host = "raw.githubusercontent.com/chr233";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host, github_host);
return fetch(url, {
method: request.method,
headers: {
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
}
});
}
}
- Download
export default {
async fetch(request, env, ctx) {
const { host, pathname } = new URL(request.url);
if (pathname === '/') {
return new Response(`this is a mirror of https://github.com\r\nsuch as https://github.com/chr233/ASFEnhance/releases/download/2.3.12.0/ASFEnhance.zip -> https://${host}/ASFEnhance/releases/download/2.3.12.0/ASFEnhance.zip`, { status: 200 });
}
// GitHub 仓库文件地址
const github_host = "github.com/chr233";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host, github_host);
return fetch(url,{
method: request.method,
headers: {
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
},
});
}
}
方案二, 一个Worker, 按照不同路径代理不同的域名
需要设置 GH_TOKEN
, 和 PackageNames
因为代理的仓库所有者为 Xposed-Modules-Repo
, 额外添加了仓库名白名单, 只有白名单内的仓库进行反代
PackageNames
示例值: ["com.chrxw.purenga"]
export default {
async fetch(request, env, ctx) {
const { PackageNames, GH_TOKEN } = env;
const { host, pathname } = new URL(request.url);
if (pathname.startsWith("/dl/")) {
const entries = pathname.toLowerCase().split('/');
if (entries.length < 3 || !entries[2]) {
const demoPackage = PackageNames[0];
return new Response(`this is a mirror of https://api.github.com, missing packageName, such as: https://${host}/${demoPackage} -> https://api.github.com/repos/Xposed-Modules-Repo/${demoPackage}`, { status: 200 });
}
const currentPackageName = entries[2];
let valid = false;
for (const name of PackageNames) {
if (currentPackageName == name) {
valid = true;
break;
}
}
if (!valid) {
return new Response(`this is a mirror of https://api.github.com, deny package name ${currentPackageName}`, { status: 403 });
}
// GitHub 仓库文件地址
const github_host = "github.com/Xposed-Modules-Repo";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host + "/dl", github_host);
const response = await fetch(url, {
headers: {
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
}
});
return response;
} else if (pathname.startsWith("/raw/")) {
const entries = pathname.toLowerCase().split('/');
if (entries.length < 3 || !entries[2]) {
const demoPackage = PackageNames[0];
return new Response(`this is a mirror of https://api.github.com, missing packageName, such as: https://${host}/${demoPackage} -> https://api.github.com/repos/Xposed-Modules-Repo/${demoPackage}`, { status: 200 });
}
const currentPackageName = entries[2];
let valid = false;
for (const name of PackageNames) {
if (currentPackageName == name) {
valid = true;
break;
}
}
if (!valid) {
return new Response(`this is a mirror of https://api.github.com, deny package name ${currentPackageName}`, { status: 403 });
}
// GitHub 仓库文件地址
const github_host = "raw.githubusercontent.com/Xposed-Modules-Repo";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host + "/raw", github_host);
const response = await fetch(url, {
headers: {
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
}
});
return response;
} else {
const entries = pathname.toLowerCase().split('/');
if (entries.length < 2 || !entries[1]) {
const demoPackage = PackageNames[0];
return new Response(`this is a mirror of https://api.github.com, missing packageName, such as: https://${host}/${demoPackage} -> https://api.github.com/repos/Xposed-Modules-Repo/${demoPackage}`, { status: 200 });
}
const currentPackageName = entries[1];
let valid = false;
for (const name of PackageNames) {
if (currentPackageName == name) {
valid = true;
break;
}
}
if (!valid) {
return new Response(`this is a mirror of https://github.com/, deny package name ${currentPackageName}`, { status: 403 });
}
// GitHub 仓库文件地址
const github_host = "api.github.com/repos/Xposed-Modules-Repo";
// 替换 2 次以同时兼容 Worker 来源和域名来源
const url = request.url.replace(host, github_host);
const response = await fetch(url, {
headers: {
"Authorization": `Bearer ${GH_TOKEN}`,
"User-Agent": request.headers.get('user-agent'),
"Referer": request.headers.get('referer'),
}
});
const target_host = "https://github.com/Xposed-Modules-Repo";
const mirror_host = `https://${host}/dl`;
const body = await response.text()
const new_body = body.replaceAll(target_host, mirror_host)
return new Response(new_body, response);
}
}
}
本文链接:https://blog.chrxw.com/archives/2025/09/29/1788.html
转载请保留本文链接,谢谢