export default { async fetch(request) { const url = new URL(request.url); const tunnelHost = 'instructional-qty-curriculum-protected.trycloudflare.com'; const targetUrl = `https://${tunnelHost}${url.pathname}${url.search}`; const modifiedHeaders = new Headers(request.headers); modifiedHeaders.set('Host', tunnelHost); modifiedHeaders.delete('cf-connecting-ip'); modifiedHeaders.delete('cf-ray'); modifiedHeaders.delete('cf-visitor'); const init = { method: request.method, headers: modifiedHeaders, redirect: 'manual', // Handle redirects ourselves }; if (request.method !== 'GET' && request.method !== 'HEAD') { init.body = request.body; } const response = await fetch(targetUrl, init); // Build response headers const newHeaders = new Headers(); // Copy content-type const ct = response.headers.get('content-type'); if (ct) newHeaders.set('Content-Type', ct); // Copy ALL set-cookie headers (critical for Flask sessions) const cookies = response.headers.getAll ? response.headers.getAll('set-cookie') : []; if (cookies.length === 0) { // Fallback for environments without getAll const sc = response.headers.get('set-cookie'); if (sc) newHeaders.append('Set-Cookie', sc); } else { for (const c of cookies) { newHeaders.append('Set-Cookie', c); } } // Handle redirects — rewrite tunnel URLs to our domain if (response.status >= 300 && response.status < 400) { let loc = response.headers.get('location') || ''; loc = loc.replace(`https://${tunnelHost}`, 'https://thenichequiz.com'); // Also handle relative redirects if (loc.startsWith('/')) loc = `https://thenichequiz.com${loc}`; newHeaders.set('Location', loc); return new Response(null, { status: response.status, headers: newHeaders }); } // Copy content-disposition for CSV downloads const cd = response.headers.get('content-disposition'); if (cd) newHeaders.set('Content-Disposition', cd); // Copy content-length const cl = response.headers.get('content-length'); if (cl) newHeaders.set('Content-Length', cl); newHeaders.set('Cache-Control', 'no-cache, no-store, must-revalidate'); newHeaders.set('X-Content-Type-Options', 'nosniff'); // Stream the body directly (works for images, HTML, JSON, CSV, everything) return new Response(response.body, { status: response.status, statusText: response.statusText, headers: newHeaders, }); } };