极简 GitHub Porxy 支持GitHub脚本的无限嵌套调用
前言
当我看到这个DD系统的项目时 https://github.com/bin456789/reinstall
我被它的安装命令吸引了.
curl -O https://raw.githubusercontent.com/bin456789/reinstall/main/reinstall.sh || wget -O ${_##*/} $_
找GPT解析了一下原理, 是为了考虑到有些linux系统默认有wget,有些默认有curl .
我准备把我的极简一键脚本的安装方式都改成这样.
curl -LO https://github.com/crazypeace/xray-vless-reality/raw/main/install.sh || wget -O ${_##*/}$_ && bash install.sh 4 8443
然后在脚本的一开始, 安装 curl 和 wget.
apt-get -y install curl wget -qq
我倾向于显示错误内容, 这样在小白反馈问题的时候, 直接发截图或日志就行了. 所以curl和wget没有加静默参数.
复杂的脚本命令, 在结合我的ghproxy时, 如果要实现嵌套github脚本调用, 现有的方案会比较难处理.
我准备改用 WJQSERVER-ghproxy 的思路.
在ghproxy 本身的处理过程中, 针对 .sh 的资源, 全量查找替换, 把访问github资源的链接, 都再套一次自己 ghproxy. 然后再返回.
不影响原来使用 gh-proxy 的用户.
worker.js
我想了一下,
基于 cloudflare 的 woker, 开发 一个专门 反向代理 github 的工具1. 本代理 接收的 path部分 应该是一个 http:// 或者 https://2. 如果 path部分 不是 http:// 或者 https:// 开头那么加上 http:// 或者 https://3. 判断 本代理 接收的 链接 是否 github判断方法为:链接 的域名部分 应该是 git 开头的主域名如github.comraw.githubusercontent.comapi.github.comgist.github.comcodeload.github.comavatars.githubusercontent.comassets-cdn.github.com这些域名的 主域名 都是 git 开头的4. 在获取需要反向代理的内容后检查 path 是否以 .sh 结尾, 来判断 是否 脚本文件5. 对于 .sh 结尾的脚本文件对文本内容进行查找替换将 github 的链接前面都加上 本代理的域名,这样可以解决脚本嵌套使用的场景判断 是否 github 链接的方法 参考 第3步
把上面这些需求发给GPT.
走读代码, 提一些小修小改的要求.
就得到了我们的 worker.js
addEventListener('fetch', event => {event.respondWith(handleRequest(event.request));});/*** 处理所有传入的请求* @param {Request} request*/async function handleRequest(request) {const url = new URL(request.url);const workerUrl = url.origin; // 获取 worker 自己的域名, e.g., https://my-worker.example.com// 1. 本代理 接受的 path 部分 应该是一个 http:// 或者 https://// 我们从 path 中提取目标 URLlet path = url.pathname.substring(1); // 移除开头的 '/'if (!path || path === 'favicon.ico') {return new Response('使用方法: ' + workerUrl + '/<您要代理的GitHub链接>', { status: 400 });}// 2. 如果 path 部分 不是 http:// 或者 https:// 开头, 那么加上 https://if (!path.startsWith('http://') && !path.startsWith('https://')) {path = 'https://' + path;}let targetUrl;try {targetUrl = new URL(path);} catch (e) {return new Response('路径中包含无效的 URL', { status: 400 });}// 3. 判断 本代理 接受的 链接 是否 githubif (!isGitHubDomain(targetUrl.hostname)) {return new Response('访问被拒绝:此代理仅支持 GitHub 相关域名。', { status: 403 });}// 准备转发请求// GET 或 HEAD 方法不能有 bodyconst hasBody = request.method === 'POST' || request.method === 'PUT' || request.method === 'PATCH';const response = await fetch(targetUrl.toString(), {method: request.method,headers: request.headers,body: hasBody ? request.body : null,redirect: 'follow',});// 复制响应头,并设置 CORSconst newHeaders = new Headers(response.headers);newHeaders.set('access-control-allow-origin', '*');newHeaders.set('access-control-allow-headers', '*');newHeaders.set('access-control-allow-methods', '*');// 4. 检查 path 是否以 .sh 结尾const finalUrl = new URL(response.url);const isScript = finalUrl.pathname.endsWith('.sh');// 5. 对于 .sh 结尾的脚本文件 (并且请求成功)if (isScript && response.status === 200) {let bodyText = await response.text();// ********** git.io 短链 ************// 修复 git.io 链接:[空格]git.io 替换为 [空格]https://git.iobodyText = bodyText.replace(/(\s)(git\.io)/g, '$1https://$2');// **********************************// 对所有 GitHub 链接进行查找替换 (嵌套代理)// 匹配所有 https?://... 链接const urlRegex = /(https?:\/\/[^\s"'`()<>]+)/g;bodyText = bodyText.replace(urlRegex, (match) => {try {// 'match' 是一个完整的 URL, e.g., "https://github.com/foo"const linkUrl = new URL(match);// 使用 isGitHubDomain 函数来判断if (isGitHubDomain(linkUrl.hostname)) {// 如果是 GitHub 链接,添加代理前缀return `${workerUrl}/${match}`;} else {// 如果不是,保持原样return match;}} catch (e) {// 如果 URL 解析失败 (例如,它可能只是看起来像 URL 的文本),保持原样return match;}});// 因为修改了内容,所以 content-length 头部失效了,删除它newHeaders.delete('content-length');return new Response(bodyText, {status: response.status,statusText: response.statusText,headers: newHeaders,});}// 对于非 .sh 文件或非 200 状态码,直接返回(已修改 CORS 和 Location 头部)return new Response(response.body, {status: response.status,statusText: response.statusText,headers: newHeaders,});}/*** 助手函数:判断是否为目标的 GitHub 域名* 域名是否以 git 开头* @param {string} hostname* @returns {boolean}*/function isGitHubDomain(hostname) {// 这个正则表达式检查:// 1. (^|\.) : 字符串是否以...开头 (^) 或 ( | ) 以一个点 (.) 开头// 2. git : 后面紧跟着 'git'//// 示例:// - "github.com" -> 匹配 (^git)// - "api.github.com" -> 匹配 (.git)hub.com// - "gitlab.com" -> 匹配 (^git)// - "my.gitee.com" -> 匹配 (.git)ee.com// - "my-git.com" -> 不匹配 (因为 'g' 前面是 '-' 而不是 '.' 或开头)return /(^|\.)git/.test(hostname);}
index.html
工具页面 index.html 本身与 github proxy 是相对独立的.
html内容很少, 也很简单.
参考之前的 gh-proxy 的 index.html 删掉一些界面元素, 调整一些文字说明就行了.
main.js
工具页面 index.html上点击按钮时, 将链接添加ghproxy的工作是在 main.js 中完成的.
借用 worker.js 中的实现, 正好都是JS, 代码直接复制粘贴就行了.
访问worker时, 显示index.html
处理 path 为空时, path 为 styles.css 时, path 为 main.js 时, 应该去访问 github page
// 如果path为空,返回主页if (!path) {return fetch(ASSET_URL)}if (path === 'styles.css') {return fetch(ASSET_URL + path)}if (path === 'main.js') {return fetch(ASSET_URL + path)}
上传 Github
演示站
演示视频
部署方法
========
后记
在本次 (2025-11-6) 面向GPT开发中最好用的GPT是

评论
发表评论