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.
110 lines
2.6 KiB
110 lines
2.6 KiB
2 years ago
|
'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,
|
||
|
})
|
||
|
}
|