"use strict";
const ASSET_URL = "https://hunshcn.github.io/gh-proxy";
const PREFIX = "/";
const Config = { jsdelivr: 1, cnpmjs: 1, };
const PREFLIGHT_INIT = { status: 204, headers: new Headers({ "access-control-allow-origin": "*", "access-control-allow-methods": "GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS", "access-control-max-age": "1728000", }), };
function makeRes(body, status = 200, headers = {}) { headers["access-control-allow-origin"] = "*"; return new Response(body, { status, headers }); }
function newUrl(urlStr) { try { return new URL(urlStr); } catch (err) { return null; } }
addEventListener("fetch", (e) => { const ret = fetchHandler(e).catch((err) => makeRes("cfworker error:\n" + err.stack, 502) ); e.respondWith(ret); });
async function fetchHandler(e) { const req = e.request; const urlStr = req.url; const urlObj = new URL(urlStr); let path = urlObj.searchParams.get("q"); if (path) { return Response.redirect("https://" + urlObj.host + PREFIX + path, 301); } path = urlObj.href .substr(urlObj.origin.length + PREFIX.length) .replace(/^https?:\/+/, "https://"); const exp1 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:releases|archive)\/.*$/i; const exp2 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:blob)\/.*$/i; const exp3 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:info|git-upload-pack).*$/i; const exp4 = /^(?:https?:\/\/)?raw\.githubusercontent\.com\/.+?\/.+?\/.+?\/.+$/i; if ( path.search(exp1) === 0 || (!Config.jsdelivr && path.search(exp2) === 0) || (!Config.cnpmjs && (path.search(exp3) === 0 || path.search(exp4))) ) { return httpHandler(req, path); } else if (path.search(exp2) === 0) { const newUrl = path .replace("/blob/", "@") .replace(/^(?:https?:\/\/)?github\.com/, "https://cdn.jsdelivr.net/gh"); return Response.redirect(newUrl, 302); } else if (path.search(exp3) === 0) { const newUrl = path.replace( /^(?:https?:\/\/)?github\.com/, "https://github.com.cnpmjs.org" ); return Response.redirect(newUrl, 302); } else if (path.search(exp4) === 0) { const newUrl = path .replace(/(?<=com\/.+?\/.+?)\/(.+?\/)/, "@$1") .replace( /^(?:https?:\/\/)?raw\.githubusercontent\.com/, "https://cdn.jsdelivr.net/gh" ); return Response.redirect(newUrl, 302); } else { return fetch(ASSET_URL + path); } }
function httpHandler(req, pathname) { const reqHdrRaw = req.headers;
if ( req.method === "OPTIONS" && reqHdrRaw.has("access-control-request-headers") ) { return new Response(null, PREFLIGHT_INIT); }
let rawLen = "";
const reqHdrNew = new Headers(reqHdrRaw);
let urlStr = pathname; if (urlStr.startsWith("github")) { urlStr = "https://" + urlStr; } const urlObj = newUrl(urlStr);
const reqInit = { method: req.method, headers: reqHdrNew, redirect: "follow", body: req.body, }; return proxy(urlObj, reqInit, rawLen, 0); }
async function proxy(urlObj, reqInit, rawLen) { const res = await fetch(urlObj.href, reqInit); const resHdrOld = res.headers; const resHdrNew = new Headers(resHdrOld);
if (rawLen) { const newLen = resHdrOld.get("content-length") || ""; const badLen = rawLen !== newLen;
if (badLen) { return makeRes(res.body, 400, { "--error": `bad len: ${newLen}, except: ${rawLen}`, "access-control-expose-headers": "--error", }); } } const status = res.status; resHdrNew.set("access-control-expose-headers", "*"); resHdrNew.set("access-control-allow-origin", "*");
resHdrNew.delete("content-security-policy"); resHdrNew.delete("content-security-policy-report-only"); resHdrNew.delete("clear-site-data");
return new Response(res.body, { status, headers: resHdrNew, }); }
|