export default { async fetch(request, env, context) { return await handleRequest(request, env, context) } } async function handleRequest(request, {pageUrl, codeUrl}, context) { const url = new URL(request.url); const allowOrigin = request.headers.get('Origin') || url.origin; const pathPrefix = '/b23/'; const pathname = url.pathname.startsWith(pathPrefix) ? url.pathname.slice(pathPrefix.length - 1) : url.pathname; const routeJsonResult = '/g'; const response = await caches.default.match(request); if (response) { return response; } if (pathname === '/' || pathname === '/index.html') { const {status, body} = await fetch(pageUrl); return new Response(body, { status, headers: { "content-type": "text/html; charset=utf-8", } }); } if (pathname === '/worker.js') { const {status, body} = await fetch(codeUrl); return new Response(body, { status, headers: { "content-type": "text/plain;charset=utf-8" } }); } // invalid pathnames should be handled here if (pathname.includes('.')) { return new Response("400 Bad Request.", { status: 400, headers: { 'Cache-Control': 'public, max-age=31536000', }, }); } if (request.method === "OPTIONS") { // Handle CORS preflight requests if ( request.headers.get("Origin") !== null && request.headers.get("Access-Control-Request-Method") !== null && request.headers.get("Access-Control-Request-Headers") !== null ) { return new Response(null, { headers: { "Access-Control-Allow-Origin": allowOrigin, "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS", "Access-Control-Max-Age": "86400", "Access-Control-Allow-Headers": request.headers.get( "Access-Control-Request-Headers" ), }, }); } else { // Handle standard OPTIONS request. return new Response(null, { headers: { Allow: "GET, HEAD, POST, OPTIONS", }, }); } } const g = pathname.startsWith(routeJsonResult); const b23 = new URL(g ? pathname.slice(routeJsonResult.length) : pathname, 'https://b23.tv'); const paramsToReserve = [ 'p', 'page', 't', 'itemsId', 'tab', 'topic_id', 'vote_id' ]; let returned; await fetch(b23, { redirect: "manual", }) .then((response) => { if (response.status === 302 || response.status === 301) { const orgUrl = new URL(response.headers.get('Location') || 'https://www.bilibili.com/'); const newUrl = new URL(orgUrl.pathname, orgUrl.origin); const search = new URLSearchParams(); orgUrl.searchParams.forEach((value, key) => { if (paramsToReserve.includes(key)) { search.append(key, value); } }); newUrl.search = search.toString(); if (g) { returned = new Response(JSON.stringify({ 'stripped': newUrl.toString(), 'url': response.headers.get('Location'), 'oq': b23.toString(), }), { status: 200, headers: { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'public, max-age=31536000', 'Referrer-Policy': 'no-referrer', 'Access-Control-Allow-Origin': allowOrigin, }, }); return; } const modifiedHeaders = new Headers(response.headers); modifiedHeaders.set('Access-Control-Allow-Origin', allowOrigin); modifiedHeaders.set('Cache-Control', 'public, max-age=31536000'); modifiedHeaders.set('Referrer-Policy', 'no-referrer'); modifiedHeaders.set('Location', newUrl.toString()); returned = new Response(response.body, { ...response, headers: modifiedHeaders, }); context.waitUntil(caches.default.put(request, returned.clone())); } else { const modifiedHeaders = new Headers(response.headers); modifiedHeaders.set('Access-Control-Allow-Origin', allowOrigin); returned = new Response(response.body, { status: Number.parseInt(response.headers.get('bili-status-code').slice(1)), headers: modifiedHeaders, }); } }); return returned; }