mirror of https://github.com/hunshcn/gh-proxy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.6 KiB
109 lines
2.6 KiB
'use strict' |
|
|
|
/** @type {RequestInit} */ |
|
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', |
|
}), |
|
} |
|
|
|
const PREFIX = 'https://example.com/' |
|
|
|
|
|
/** |
|
* @param {any} body |
|
* @param {number} status |
|
* @param {Object<string, string>} headers |
|
*/ |
|
function makeRes(body, status = 200, headers = {}) { |
|
headers['access-control-allow-origin'] = '*' |
|
return new Response(body, {status, headers}) |
|
} |
|
|
|
|
|
addEventListener('fetch', e => { |
|
const ret = fetchHandler(e) |
|
.catch(err => makeRes('cfworker error:\n' + err.stack, 502)) |
|
e.respondWith(ret) |
|
}) |
|
|
|
|
|
/** |
|
* @param {FetchEvent} e |
|
*/ |
|
async function fetchHandler(e) { |
|
const req = e.request |
|
const urlStr = req.url |
|
const urlObj = new URL(urlStr) |
|
let path = urlStr.substring(urlObj.origin.length + 1).replace(/^(https?):\/+/, '$1://') |
|
return httpHandler(req, path) |
|
} |
|
|
|
|
|
/** |
|
* @param {Request} req |
|
* @param {string} pathname |
|
*/ |
|
function httpHandler(req, pathname) { |
|
const reqHdrRaw = req.headers |
|
|
|
// preflight |
|
if (req.method === 'OPTIONS' && |
|
reqHdrRaw.has('access-control-request-headers') |
|
) { |
|
return new Response(null, PREFLIGHT_INIT) |
|
} |
|
|
|
const reqHdrNew = new Headers(reqHdrRaw) |
|
|
|
/** @type {RequestInit} */ |
|
const reqInit = { |
|
method: req.method, |
|
headers: reqHdrNew, |
|
redirect: 'manual', |
|
body: req.body |
|
} |
|
return proxy(pathname, reqInit) |
|
} |
|
|
|
|
|
/** |
|
* |
|
* @param {string} path |
|
* @param {RequestInit} reqInit |
|
*/ |
|
async function proxy(path, reqInit) { |
|
const res = await fetch(path, reqInit) |
|
const resHdrOld = res.headers |
|
const resHdrNew = new Headers(resHdrOld) |
|
|
|
const status = res.status |
|
|
|
if (resHdrNew.has('location')) { |
|
let _location = resHdrNew.get('location') |
|
resHdrNew.set('location', PREFIX + _location) |
|
} |
|
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') |
|
if (path.substring(0, path.lastIndexOf("/")).endsWith('/info/lfs/objects')) { |
|
let text = await res.text() |
|
text = text.replaceAll('"href":"https://', '"href":"' + PREFIX + 'https://') |
|
resHdrNew.delete("content-length") |
|
return new Response(text, { |
|
status, |
|
headers: resHdrNew, |
|
}) |
|
} |
|
|
|
return new Response(res.body, { |
|
status, |
|
headers: resHdrNew, |
|
}) |
|
}
|
|
|