const handleRequest = async (request) => { try { const url = new URL(request.url); let query; let dropHeaders = false; if (url.search.includes('&dh')) { url.search = url.search.replace('&dh', ''); dropHeaders = true; } if (url.search.includes('?q=')) { query = url.search.split('?q=')[1]; } else if (url.search.includes('?d=')) { query = atob(url.search.split('?d=')[1]); } else if (url.search.includes('?d2=')) { const fullEncodedURL = url.search.split('?d2=')[1]; const key = parseInt(fullEncodedURL.slice(-2)); query = atob(fullEncodedURL.slice(0, -2)) .split(':') .map((char) => String.fromCharCode(char - key)) .join(''); } else { return new Response(null, { status: 400, statusText: 'Bad Request', }); } request = new Request(query, request); request.headers.set('Host', new URL(query).origin); request.headers.set('Referrer', new URL(query)); request.headers.set('Origin', new URL(query)); request.headers.set('Access-Control-Allow-Credentials', 'true'); request.headers.delete('X-Content-Type-Options'); let response = await fetch(request); response = new Response(response.body, response); if (dropHeaders) response.headers.forEach((_, key) => response.headers.delete(key)); response.headers.set('Access-Control-Allow-Origin', 'https://due.moe'); response.headers.append('Vary', 'Origin'); response.headers.set('Cache-Control', 'max-age=300'); return response; } catch { return new Response(null, { status: 400, statusText: 'Bad Request', }); } }; const handleOptions = async (request) => { 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': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS', 'Access-Control-Allow-Headers': '*', }, }); } else { return new Response(null, { headers: { Allow: 'GET, HEAD, POST, OPTIONS', }, }); } }; addEventListener('fetch', (event) => { const request = event.request; try { switch (request.method) { case 'OPTIONS': event.respondWith(handleOptions(request)); break; case 'GET': case 'HEAD': case 'POST': event.respondWith(handleRequest(request)); break; default: event.respondWith(async () => { return new Response(null, { status: 405, statusText: 'Method Not Allowed', }); }); break; } } catch { return new Response(null, { status: 400, statusText: 'Bad Request', }); } });