'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} 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, }) }