-
-
Save derom/3197260b13245d7acaedeb2351049c4f to your computer and use it in GitHub Desktop.
rebelboost cloudflare worker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| addEventListener('fetch', event => { | |
| event.respondWith(handleRequest(event.request)) | |
| }) | |
| async function handleRequest(request) { | |
| const url = new URL(request.url) | |
| const originalHost = url.host | |
| // Determine if we should try the rebelboost origin | |
| const shouldUseRebelboost = checkRebelboostFlag(request) | |
| if (shouldUseRebelboost === false) { | |
| // Explicitly set to false, use original origin | |
| return fetch(request) | |
| } | |
| if (shouldUseRebelboost === true) { | |
| // Try rebelboost origin with fallback to original | |
| return handleRequestWithFailover(request, url, originalHost) | |
| } | |
| // No rebelboost flag set, use original origin | |
| return fetch(request) | |
| } | |
| async function handleRequestWithFailover(request, url, originalHost) { | |
| const primaryOrigin = 'https://ingressv2.rebelboost.com' | |
| const failoverStatusCodes = [500, 502, 503, 504] | |
| const TIMEOUT_MS = 10000 // 10 second timeout for primary origin | |
| // Create the modified request for primary origin | |
| const primaryRequest = createModifiedRequest( | |
| request, | |
| url, | |
| primaryOrigin, | |
| originalHost | |
| ) | |
| try { | |
| // Race between primary request and timeout | |
| const primaryResponse = await Promise.race([ | |
| fetch(primaryRequest), | |
| new Promise((_, reject) => | |
| setTimeout(() => reject(new Error('Timeout')), TIMEOUT_MS) | |
| ) | |
| ]) | |
| // Check status code immediately without reading the body | |
| if (failoverStatusCodes.includes(primaryResponse.status)) { | |
| console.log(`Primary origin returned ${primaryResponse.status}, failing over`) | |
| return fetch(request) | |
| } | |
| // Return the response immediately, streaming will happen automatically | |
| return primaryResponse | |
| } catch (error) { | |
| // Primary origin failed or timed out | |
| console.log(`Primary origin failed: ${error.message}, failing over`) | |
| return fetch(request) | |
| } | |
| } | |
| function createModifiedRequest(request, url, newOrigin, originalHost) { | |
| // Update the URL with the new origin | |
| const modifiedUrl = new URL(url.toString()) | |
| const originUrl = new URL(newOrigin) | |
| modifiedUrl.hostname = originUrl.hostname | |
| modifiedUrl.protocol = originUrl.protocol | |
| modifiedUrl.port = originUrl.port | |
| // Clone the request headers and add x-forwarded-host header | |
| const newHeaders = new Headers(request.headers) | |
| newHeaders.set('x-forwarded-host', originalHost) | |
| // Create a new request with the updated URL and headers | |
| return new Request(modifiedUrl.toString(), { | |
| method: request.method, | |
| headers: newHeaders, | |
| body: request.body, | |
| redirect: request.redirect, | |
| cf: request.cf | |
| }) | |
| } | |
| function checkRebelboostFlag(request) { | |
| const url = new URL(request.url) | |
| // Check query parameter first (higher priority) | |
| const queryParam = url.searchParams.get('rebelboost') | |
| if (queryParam === 'true') { | |
| return true | |
| } | |
| if (queryParam === 'false') { | |
| return false | |
| } | |
| // Check cookie header if no query param | |
| const cookieHeader = request.headers.get('Cookie') | |
| if (!cookieHeader) { | |
| return null | |
| } | |
| // Parse cookies and check for rebelboost value | |
| const cookies = parseCookies(cookieHeader) | |
| if (cookies.rebelboost === 'true') { | |
| return true | |
| } | |
| if (cookies.rebelboost === 'false') { | |
| return false | |
| } | |
| // No rebelboost flag set | |
| return null | |
| } | |
| function parseCookies(cookieHeader) { | |
| const cookies = {} | |
| cookieHeader.split(';').forEach(cookie => { | |
| const [name, value] = cookie.trim().split('=') | |
| if (name && value) { | |
| cookies[name] = decodeURIComponent(value) | |
| } | |
| }) | |
| return cookies | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment