diff --git a/dist/README.md b/dist/README.md
index f36cdba..60bff4b 100644
--- a/dist/README.md
+++ b/dist/README.md
@@ -1 +1 @@
-This folder contains the built output assets for the worker "crowdhandler-integration" generated at 2026-04-27T14:01:55.277Z.
\ No newline at end of file
+This folder contains the built output assets for the worker "crowdhandler-integration" generated at 2026-06-09T11:27:13.384Z.
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
index e3aaca0..1b744b6 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -371,7 +371,22 @@ async function handleRequest(request, env, ctx) {
const path = urlAttributes.pathname;
const requestHeaders = Object.fromEntries(request.headers);
const unprocessedQueryString = urlAttributes.search;
- const IPAddress = requestHeaders["cf-connecting-ip"] || null;
+ const fallbackIP = requestHeaders["cf-connecting-ip"] || null;
+ let IPAddress = fallbackIP;
+ try {
+ if (env.IP_HEADER) {
+ const overrideValue = requestHeaders[env.IP_HEADER.toLowerCase()];
+ if (overrideValue) {
+ const parsed = overrideValue.split(",")[0].trim();
+ if (parsed) {
+ IPAddress = parsed;
+ }
+ }
+ }
+ } catch (error) {
+ console.error("IP_HEADER override failed, falling back to cf-connecting-ip:", error);
+ IPAddress = fallbackIP;
+ }
const userAgent = requestHeaders["user-agent"] || null;
const validToken = /(.*\d+.*)/;
let language = null;
diff --git a/dist/index.js.map b/dist/index.js.map
index d558704..6ca360f 100644
--- a/dist/index.js.map
+++ b/dist/index.js.map
@@ -2,7 +2,7 @@
"version": 3,
"sources": ["../node_modules/await-timeout/src/utils.js", "../node_modules/await-timeout/src/index.js", "../helpers/misc.js", "../helpers/http.js", "../index.js"],
"sourceRoot": "dist",
- "sourcesContent": ["exports.promiseFinally = (promise, fn) => {\n const success = result => {\n fn();\n return result;\n };\n const error = e => {\n fn();\n return Promise.reject(e);\n };\n return Promise.resolve(promise).then(success, error);\n};\n\n/**\n * Converts any value to Error.\n * @param {*} value\n * @returns {Error}\n */\nexports.toError = value => {\n value = typeof value === 'function' ? value() : value;\n return typeof value === 'string' ? new Error(value) : value;\n};\n", "/**\n * Promise-based replacement for setTimeout / clearTimeout.\n */\n\nconst {promiseFinally, toError} = require('./utils');\n\nmodule.exports = class Timeout {\n static set(delay, rejectReason) {\n return new Timeout().set(delay, rejectReason);\n }\n\n static wrap(promise, delay, rejectReason) {\n return new Timeout().wrap(promise, delay, rejectReason);\n }\n\n constructor() {\n this._id = null;\n this._delay = null;\n }\n\n get id() {\n return this._id;\n }\n\n get delay() {\n return this._delay;\n }\n\n set(delay, rejectReason = '') {\n return new Promise((resolve, reject) => {\n this.clear();\n const fn = rejectReason ? () => reject(toError(rejectReason)) : resolve;\n this._id = setTimeout(fn, delay);\n this._delay = delay;\n });\n }\n\n wrap(promise, delay, rejectReason = '') {\n const wrappedPromise = promiseFinally(promise, () => this.clear());\n const timer = this.set(delay, rejectReason);\n return Promise.race([\n wrappedPromise,\n timer\n ]);\n }\n\n clear() {\n if (this._id) {\n clearTimeout(this._id);\n }\n }\n};\n", "const helpers = {\n //List of known static file extensions that should never be subjected to queueing.\n creativeAssetExtensions: [\n 'avi',\n 'css',\n 'csv',\n 'eot',\n 'gif',\n 'ico',\n 'jpg',\n 'js',\n 'json',\n 'map',\n 'mov',\n 'mp4',\n 'mpeg',\n 'mpg',\n 'ogg',\n 'ogv',\n 'ott',\n 'pdf',\n 'png',\n 'svg',\n 'ttf',\n 'webmanifest',\n 'wmv',\n 'woff',\n 'woff2',\n 'xml',\n ],\n //regex for matching wordpress urls and query strings\n wordpressExclusions: /(w[cp][-_](?![-_])(?!order_).*|xmlrpc\\.php|readme\\.html|license\\.txt|trackback|feed(?:\\/.*)?|comments\\/feed(?:\\/.*)?)(\\?.*)?/,\n noCacheHeaders: {\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Expires: 'Fri, 01 Jan 1970 00:00:00 GMT',\n Pragma: 'no-cache',\n },\n lottery: function(roofInteger) {\n return Math.floor(Math.random() * parseInt(roofInteger))\n },\n parseCookies: function(headers) {\n const parsedCookie = {}\n if (headers.cookie) {\n headers.cookie.split(';').forEach(cookie => {\n if (cookie) {\n const parts = cookie.split('=')\n if (parts[1] !== undefined) {\n parsedCookie[parts[0].trim()] = parts[1].trim()\n }\n }\n })\n }\n return parsedCookie\n },\n //Build a Set-Cookie value for the crowdhandler token, optionally with a\n //Domain attribute so the cookie can be shared across subdomains of the\n //configured parent. The raw value is trimmed and validated against\n //hostname-safe characters so a typo'd or malicious env var can't inject\n //into the Set-Cookie header.\n buildCrowdhandlerCookie: function(tokenValue, rawCookieDomain) {\n const parts = [`crowdhandler=${tokenValue}`, 'path=/', 'Secure']\n if (rawCookieDomain) {\n const trimmed = String(rawCookieDomain).trim()\n if (/^\\.?[a-zA-Z0-9.-]+$/.test(trimmed)) {\n parts.push(`Domain=${trimmed}`)\n } else {\n console.warn(`[CH] Ignoring invalid COOKIE_DOMAIN value: ${JSON.stringify(rawCookieDomain)}`)\n }\n }\n return parts.join('; ')\n },\n queryStringParse: function(querystring) {\n const params = new URLSearchParams(querystring)\n let qStrObject = {}\n\n for (let item of params) {\n if (qStrObject.hasOwnProperty(item[0])) {\n if (Array.isArray(qStrObject[item[0]])) {\n qStrObject[item[0]].push(item[1])\n } else {\n qStrObject[item[0]] = [qStrObject[item[0]], item[1]]\n }\n } else {\n qStrObject[item[0]] = item[1]\n }\n }\n //return as object\n return qStrObject\n },\n}\n\nexport default helpers\n", "// Server error response (5xx, network errors) - respects failTrust setting\nconst dummyResponseData = {\n result: {\n status: 2,\n token: null,\n title: null,\n position: null,\n live_position: null,\n promoted: null,\n urlRedirect: null,\n onsale: null,\n message: null,\n slug: null,\n priority: null,\n priorityAvailable: null,\n logo: null,\n responseID: null,\n captchaRequired: null,\n ttl: null,\n },\n}\n\n// Client error response (4xx) - never triggers failTrust, always safety net\nconst clientErrorResponseData = {\n result: {\n status: 2,\n clientError: true,\n token: null,\n title: null,\n position: null,\n live_position: null,\n promoted: null,\n urlRedirect: null,\n onsale: null,\n message: null,\n slug: null,\n priority: null,\n priorityAvailable: null,\n logo: null,\n responseID: null,\n captchaRequired: null,\n ttl: null,\n },\n}\n\nconst http_helpers = {\n processResponse: async function(response) {\n let fetchResponse\n let responseObject = {}\n\n fetchResponse = await response\n\n //Communication failure. No fetch response to use.\n if (!fetchResponse) {\n responseObject.body = dummyResponseData\n responseObject.status = null\n responseObject.statusText = \"Communication failure between Cloudflare and the CrowdHandler API occurred.\"\n responseObject.success = false\n return responseObject;\n //Communication success. 4xx client error returned.\n } else if (fetchResponse.status >= 400 && fetchResponse.status < 500) {\n console.error(`[CH] API 4xx: ${fetchResponse.status}`)\n responseObject.body = clientErrorResponseData\n //Communication success. 5xx server error returned.\n } else if (fetchResponse.status >= 500) {\n console.error(`[CH] API 5xx: ${fetchResponse.status}`)\n responseObject.body = dummyResponseData\n //Normal response.\n } else {\n responseObject.body = await response.json()\n }\n\n responseObject.status = fetchResponse.status\n responseObject.statusText = fetchResponse.statusText\n responseObject.success = fetchResponse.ok\n\n return responseObject\n },\n}\n\nexport default http_helpers\n", "import helpers from './helpers/misc'\nimport http_helpers from './helpers/http'\nimport Timeout from 'await-timeout'\n\nasync function handleWhitelabelRequest(request, env) {\n let fallbackPath = `/${request.queryString}`\n let slug = request.path.substring(4)\n\n let templateContentType = 'text/html;charset=UTF-8'\n let templateDomain\n\n let devPublicKeys = [\n 'dba793b5eb837611498d0b809aefdefcb6f113310b272f6114435964670125a1',\n '04a39378b6abc3e3ee870828471636a9d1e157b1a7720821aed4c260108ebe43',\n ]\n\n if (devPublicKeys.includes(env.API_KEY)) {\n templateDomain = 'wait-dev.crowdhandler.com'\n } else {\n templateDomain = 'wait.crowdhandler.com'\n }\n\n let templateEndpoint\n let templateFetchTimeout = 6000\n if (slug) {\n templateEndpoint = `https://${templateDomain}/${slug}`\n } else {\n templateEndpoint = `https://${templateDomain}${fallbackPath}`\n }\n\n let cache = await caches.open('crowdhandler:cache')\n let cacheHit = await cache.match(templateEndpoint)\n\n if (cacheHit) {\n console.log('Serving waiting room template from cache.')\n return {\n response: cacheHit,\n useCache: true,\n }\n }\n\n let httpParams = {\n headers: {\n 'content-type': templateContentType,\n },\n method: 'GET',\n }\n\n async function gatherResponse(response) {\n const { headers } = response\n const contentType = headers.get('content-type') || ''\n if (contentType.includes('application/json')) {\n return JSON.stringify(await response.json())\n } else if (contentType.includes('application/text')) {\n return response.text()\n } else if (contentType.includes('text/html')) {\n return response.text()\n } else {\n return response.text()\n }\n }\n\n let errorState\n let fetchCounter = 0\n\n async function fetchTemplate() {\n let timer = new Timeout()\n //reset the error state\n errorState = null\n let response\n try {\n fetchCounter++\n response = await Promise.race([\n fetch(templateEndpoint, httpParams),\n timer.set(templateFetchTimeout, 'API Communication Timed Out!'),\n ])\n //await fetch(templateEndpoint, httpParams)\n if (response.status !== 200) {\n throw `${response.status} ${response.statusText}`\n }\n } catch (error) {\n errorState = true\n console.error('Template Fetch Failure:', error)\n } finally {\n timer.clear()\n if (errorState === true && fetchCounter < 3) {\n console.log('Retrying Template Fetch.')\n return await fetchTemplate()\n }\n return response\n }\n }\n\n let templateResponse = await fetchTemplate()\n let results\n let resultsMeta\n\n if (templateResponse) {\n results = await gatherResponse(templateResponse)\n resultsMeta = {\n headers: {\n 'content-type': templateContentType,\n },\n status: templateResponse.status,\n statusText: templateResponse.statusText,\n }\n } else {\n results = '
Service Temporarily Unavailable
'\n resultsMeta = {\n headers: {\n 'content-type': templateContentType,\n },\n status: 503,\n statusText: 'Service Unavailable',\n }\n }\n\n return { cache, results, resultsMeta, templateEndpoint }\n}\n\nasync function handleRequest(request, env, ctx) {\n\n //Log the time that the request was initiated\n const requestStartTime = Date.now()\n //Extensions that should be passed-through\n const bypassedFileExtensions = helpers.creativeAssetExtensions\n const wordpressExclusions = helpers.wordpressExclusions\n\n //Full URL\n const url = request.url\n const urlAttributes = new URL(url)\n //Hostname\n const host = urlAttributes.hostname\n //Don't try and queue static assets\n const path = urlAttributes.pathname\n //https://developers.cloudflare.com/workers/examples/logging-headers\n const requestHeaders = Object.fromEntries(request.headers)\n //https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-\n const unprocessedQueryString = urlAttributes.search\n const IPAddress = requestHeaders['cf-connecting-ip'] || null\n const userAgent = requestHeaders['user-agent'] || null\n const validToken = /(.*\\d+.*)/\n let language = null\n let waitingRoomDomain\n\n let statusIdentifier = /^\\/ch\\/status$/\n let whiteLabelIdentifier = /^\\/ch\\/.*/\n\n //Check if the request is for a status check and handle response\n if (statusIdentifier.test(path) === true) {\n return new Response(\n JSON.stringify({ integration: 'cloudflare', status: 'ok' }),\n {\n headers: {\n 'content-type': 'text/plain',\n 'cache-control': 'public, max-age=60',\n },\n },\n )\n }\n\n //Check if the request is for a whitelabel waiting room and handle response\n if (whiteLabelIdentifier.test(path) === true) {\n //Handle the whitelabel request\n const whitelabelResponse = await handleWhitelabelRequest({\n path: path,\n queryString: unprocessedQueryString,\n }, env)\n\n //Return cached response if we have one.\n try {\n if (whitelabelResponse.useCache === true) {\n return whitelabelResponse.response\n }\n } catch (error) {\n console.error('Cache retrieval error:', error)\n }\n\n //Store template in cache\n try {\n whitelabelResponse.resultsMeta.headers['cache-control'] =\n 'public, max-age=60'\n\n if (whitelabelResponse.resultsMeta.status === 200) {\n await whitelabelResponse.cache.put(\n whitelabelResponse.templateEndpoint,\n new Response(\n whitelabelResponse.results,\n whitelabelResponse.resultsMeta,\n ),\n )\n }\n } catch (error) {\n console.error('Cache storage error:', error)\n }\n\n //Return the template\n return new Response(\n whitelabelResponse.results,\n whitelabelResponse.resultsMeta,\n )\n }\n\n //attempt to pull language from accept-language header\n try {\n language = requestHeaders['accept-language'].split(',')[0]\n } catch (error) {\n // Accept-language header not present - not critical\n }\n\n //Request object is read only so we are going to create a clone in order to be able to modify it\n const modifiedRequest = new Request(url, {\n body: request.body,\n headers: request.headers,\n method: request.method,\n redirect: request.redirect,\n })\n\n //We can't be sure that these optional environment variables exists so do a check first to avoid a reference error\n //Add x-ch-no-bypass header to request object if NO_BYPASS present in CF env variables\n if (env.NO_BYPASS) {\n modifiedRequest.headers.append('x-ch-no-bypass', env.NO_BYPASS)\n }\n\n //If environment variable is set to true, users that fail to check-in with CrowdHandler will be trusted.\n let failTrust = true\n if (env.FAIL_TRUST && env.FAIL_TRUST === 'false') {\n failTrust = false\n }\n\n //Set slug of fallback waiting room for users that fail to check-in with CrowdHandler.\n let safetyNetSlug\n if (env.SAFETY_NET_SLUG) {\n safetyNetSlug = env.SAFETY_NET_SLUG\n }\n\n //If environment variable is set to true, whitelabel waiting room will be used.\n let whitelabel = false\n if (env.WHITELABEL && env.WHITELABEL === 'true') {\n whitelabel = true\n }\n\n if (whitelabel === true) {\n waitingRoomDomain = `${host}/ch`\n } else {\n waitingRoomDomain = 'wait.crowdhandler.com'\n }\n\n //Handle static file extensions\n let fileExtension = path.match(/\\.([^.]+)$/)\n if (fileExtension !== null) {\n fileExtension = fileExtension[1]\n }\n\n if (bypassedFileExtensions.indexOf(fileExtension) !== -1) {\n return await fetch(modifiedRequest)\n }\n\n //Process query strings\n let queryString\n if (unprocessedQueryString) {\n queryString = helpers.queryStringParse(unprocessedQueryString)\n }\n\n //Destructure special params from query string if they are present\n let {\n 'ch-code': chCode,\n 'ch-fresh': chFresh,\n 'ch-id': chID,\n 'ch-id-signature': chIDSignature,\n 'ch-public-key': chPublicKey,\n 'ch-requested': chRequested,\n } = queryString || {}\n\n //Override chCode value if the current one is unusable\n if (!chCode || chCode === 'undefined' || chCode === 'null') {\n chCode = ''\n }\n\n //Remove special params from the queryString object now that we don't need them anymore\n if (queryString) {\n delete queryString['ch-code']\n delete queryString['ch-fresh']\n delete queryString['ch-id']\n delete queryString['ch-id-signature']\n delete queryString['ch-public-key']\n delete queryString['ch-requested']\n }\n\n //Convert to usable querystring format\n if (queryString && Object.keys(queryString).length !== 0) {\n let pairs = []\n for (const key of Object.keys(queryString)) {\n const values = Array.isArray(queryString[key]) ? queryString[key] : [queryString[key]]\n for (const val of values) {\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(val))\n }\n }\n\n queryString = `?${pairs.join('&')}`\n } else {\n queryString = null\n }\n\n //Handle Wordpress exclusions\n let origin_type\n if (env.ORIGIN_TYPE) {\n origin_type = env.ORIGIN_TYPE\n }\n\n if (origin_type === 'wordpress') {\n if (\n wordpressExclusions.test(path) === true ||\n wordpressExclusions.test(queryString) === true\n ) {\n return await fetch(modifiedRequest)\n }\n }\n\n //URL encode the targetURL to be used later in redirects\n let targetURL\n if (queryString) {\n targetURL = encodeURIComponent(`https://${host}${path}${queryString}`)\n } else {\n targetURL = encodeURIComponent(`https://${host}${path}`)\n }\n\n //Parse cookies\n const parsedCookies = helpers.parseCookies(requestHeaders)\n let crowdhandlerCookieValue = parsedCookies['crowdhandler']\n\n //Prioritise tokens in the ch-id parameter and fallback to ones found in the cookie\n let token\n let tokenSource\n let freshlyPromoted\n if (chID) {\n token = chID\n tokenSource = 'param'\n freshlyPromoted = true\n } else if (crowdhandlerCookieValue) {\n token = crowdhandlerCookieValue\n tokenSource = 'cookie'\n } else {\n token = null\n tokenSource = 'new'\n }\n\n //If this is a freshly promoted session, strip the special CrowdHandler parameters by issuing a redirect.\n if (freshlyPromoted) {\n let setCookie = {\n 'Set-Cookie': helpers.buildCrowdhandlerCookie(token, env.COOKIE_DOMAIN),\n }\n let redirectLocation\n if (queryString) {\n redirectLocation = { Location: `${path}${queryString}` }\n } else {\n redirectLocation = { Location: path }\n }\n return new Response(null, {\n status: 302,\n headers: Object.assign(\n helpers.noCacheHeaders,\n redirectLocation,\n setCookie,\n ),\n })\n }\n\n //Invalidate tokens that don't conform to the accepted format\n if (validToken.test(token) !== true) {\n token = null\n }\n\n //First API call here\n const apiHost = env.API_ENDPOINT\n const apiTimeout = 4000 // 4 second timeout\n let httpParams = {\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': env.API_KEY,\n },\n //choose method dynamically\n method: undefined,\n }\n\n //Determine if a GET or POST request should be made.\n let response\n let timer = new Timeout()\n\n //Make fetch\n if (token) {\n httpParams.method = 'GET'\n try {\n response = await Promise.race([\n fetch(\n `${apiHost}/requests/${token}?url=${targetURL}&agent=${encodeURIComponent(\n userAgent,\n )}&ip=${encodeURIComponent(IPAddress)}&lang=${encodeURIComponent(\n language,\n )}`,\n httpParams,\n ),\n timer.set(apiTimeout, 'CrowdHandler API request timed out'),\n ])\n } catch (error) {\n console.error('CrowdHandler API GET request failed:', error)\n response = undefined\n } finally {\n timer.clear()\n }\n } else {\n //This is a post so generate a payload and add it to the httpParams object\n httpParams.body = JSON.stringify({\n agent: userAgent,\n ip: IPAddress,\n lang: language,\n url: url,\n })\n httpParams.method = 'POST'\n try {\n response = await Promise.race([\n fetch(`${apiHost}/requests`, httpParams),\n timer.set(apiTimeout, 'CrowdHandler API request timed out'),\n ])\n } catch (error) {\n console.error('CrowdHandler API POST request failed:', error)\n response = undefined\n } finally {\n timer.clear()\n }\n }\n\n //Process fetch response\n const processResponse = http_helpers.processResponse\n const results = await processResponse(response)\n\n let responseBody\n\n //Handle API request error here\n if (results.success !== true) {\n console.error(\n `API error: ${results.status} ${results.statusText}`,\n )\n responseBody = results.body.result\n } else {\n responseBody = results.body.result\n }\n\n let redirect\n let redirectLocation\n let statusCode\n\n //Normal healthy response\n if (responseBody.promoted !== 1 && responseBody.status !== 2) {\n redirect = true\n redirectLocation = `https://${waitingRoomDomain}/${responseBody.slug}?url=${targetURL}&ch-code=${chCode}&ch-id=${responseBody.token}&ch-public-key=${env.API_KEY}`\n //4xx client error - always redirect to safety net (ignore failTrust)\n } else if (responseBody.clientError === true) {\n console.error('[CH] API returned 4xx client error - redirecting to safety net')\n redirect = true\n if (safetyNetSlug) {\n redirectLocation = `https://${waitingRoomDomain}/${safetyNetSlug}?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n } else {\n redirectLocation = `https://${waitingRoomDomain}/?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n }\n //5xx server error - respect failTrust setting\n } else if (\n failTrust !== true &&\n responseBody.promoted !== 1 &&\n responseBody.status === 2\n ) {\n redirect = true\n if (safetyNetSlug) {\n redirectLocation = `https://${waitingRoomDomain}/${safetyNetSlug}?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n } else {\n redirectLocation = `https://${waitingRoomDomain}/?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n }\n //User is promoted\n } else {\n redirect = false\n }\n\n switch (redirect) {\n case true: {\n console.log(`[CH] ${host}${path} | src:${tokenSource} | action:redirect | token:${responseBody.token || token || 'none'}`)\n if (responseBody.token) {\n return new Response(null, {\n status: 302,\n headers: Object.assign(helpers.noCacheHeaders, {\n Location: redirectLocation,\n 'Set-Cookie': helpers.buildCrowdhandlerCookie(responseBody.token, env.COOKIE_DOMAIN),\n }),\n })\n } else {\n return new Response(null, {\n status: 302,\n headers: Object.assign(helpers.noCacheHeaders, {\n Location: redirectLocation,\n }),\n })\n }\n break\n }\n case false: {\n console.log(`[CH] ${host}${path} | src:${tokenSource} | action:allow | token:${responseBody.token || 'none'}`)\n break\n }\n default: {\n break\n }\n }\n\n //We're dealing with the origin response from this point onwards\n const originResponse = await fetch(modifiedRequest)\n\n //Preserve original response but alter headers\n let modifiedOriginResponse = new Response(originResponse.body, {\n status: originResponse.status,\n statusText: originResponse.statusText,\n headers: originResponse.headers,\n })\n\n //Set token in cookie\n //Make sure we don't set invalid values\n if (validToken.test(responseBody.token) === true) {\n modifiedOriginResponse.headers.append(\n 'set-cookie',\n helpers.buildCrowdhandlerCookie(responseBody.token, env.COOKIE_DOMAIN),\n )\n }\n //Set integration method cookie\n modifiedOriginResponse.headers.append(\n 'set-cookie',\n `crowdhandler_integration=cloudflare; path=/; Secure`,\n )\n\n //End of request\n const requestEndTime = Date.now()\n\n //Send request Meta Data\n const responseID = responseBody.responseID\n\n //Send request meta information.\n async function sendRequestMeta() {\n //Sampling\n if (responseID && helpers.lottery(3) === 0) {\n httpParams.body = JSON.stringify({\n httpCode: originResponse.status,\n sampleRate: 3,\n time: requestEndTime - requestStartTime,\n })\n httpParams.method = 'PUT'\n response = await fetch(`${apiHost}/responses/${responseID}`, httpParams)\n\n const processResponse = http_helpers.processResponse\n const results = await processResponse(response)\n return results\n }\n }\n\n //This trick allows the sendRequestMeta function call to continue after we've already returned the response to the user\n //https://developers.cloudflare.com/workers/runtime-apis/context\n ctx.waitUntil(sendRequestMeta())\n\n //We're done send the response\n return modifiedOriginResponse\n}\n\nexport default {\n async fetch(request, env, ctx) {\n ctx.passThroughOnException()\n return await handleRequest(request, env, ctx)\n },\n}\n"],
- "mappings": "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",
+ "sourcesContent": ["exports.promiseFinally = (promise, fn) => {\n const success = result => {\n fn();\n return result;\n };\n const error = e => {\n fn();\n return Promise.reject(e);\n };\n return Promise.resolve(promise).then(success, error);\n};\n\n/**\n * Converts any value to Error.\n * @param {*} value\n * @returns {Error}\n */\nexports.toError = value => {\n value = typeof value === 'function' ? value() : value;\n return typeof value === 'string' ? new Error(value) : value;\n};\n", "/**\n * Promise-based replacement for setTimeout / clearTimeout.\n */\n\nconst {promiseFinally, toError} = require('./utils');\n\nmodule.exports = class Timeout {\n static set(delay, rejectReason) {\n return new Timeout().set(delay, rejectReason);\n }\n\n static wrap(promise, delay, rejectReason) {\n return new Timeout().wrap(promise, delay, rejectReason);\n }\n\n constructor() {\n this._id = null;\n this._delay = null;\n }\n\n get id() {\n return this._id;\n }\n\n get delay() {\n return this._delay;\n }\n\n set(delay, rejectReason = '') {\n return new Promise((resolve, reject) => {\n this.clear();\n const fn = rejectReason ? () => reject(toError(rejectReason)) : resolve;\n this._id = setTimeout(fn, delay);\n this._delay = delay;\n });\n }\n\n wrap(promise, delay, rejectReason = '') {\n const wrappedPromise = promiseFinally(promise, () => this.clear());\n const timer = this.set(delay, rejectReason);\n return Promise.race([\n wrappedPromise,\n timer\n ]);\n }\n\n clear() {\n if (this._id) {\n clearTimeout(this._id);\n }\n }\n};\n", "const helpers = {\n //List of known static file extensions that should never be subjected to queueing.\n creativeAssetExtensions: [\n 'avi',\n 'css',\n 'csv',\n 'eot',\n 'gif',\n 'ico',\n 'jpg',\n 'js',\n 'json',\n 'map',\n 'mov',\n 'mp4',\n 'mpeg',\n 'mpg',\n 'ogg',\n 'ogv',\n 'ott',\n 'pdf',\n 'png',\n 'svg',\n 'ttf',\n 'webmanifest',\n 'wmv',\n 'woff',\n 'woff2',\n 'xml',\n ],\n //regex for matching wordpress urls and query strings\n wordpressExclusions: /(w[cp][-_](?![-_])(?!order_).*|xmlrpc\\.php|readme\\.html|license\\.txt|trackback|feed(?:\\/.*)?|comments\\/feed(?:\\/.*)?)(\\?.*)?/,\n noCacheHeaders: {\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n Expires: 'Fri, 01 Jan 1970 00:00:00 GMT',\n Pragma: 'no-cache',\n },\n lottery: function(roofInteger) {\n return Math.floor(Math.random() * parseInt(roofInteger))\n },\n parseCookies: function(headers) {\n const parsedCookie = {}\n if (headers.cookie) {\n headers.cookie.split(';').forEach(cookie => {\n if (cookie) {\n const parts = cookie.split('=')\n if (parts[1] !== undefined) {\n parsedCookie[parts[0].trim()] = parts[1].trim()\n }\n }\n })\n }\n return parsedCookie\n },\n //Build a Set-Cookie value for the crowdhandler token, optionally with a\n //Domain attribute so the cookie can be shared across subdomains of the\n //configured parent. The raw value is trimmed and validated against\n //hostname-safe characters so a typo'd or malicious env var can't inject\n //into the Set-Cookie header.\n buildCrowdhandlerCookie: function(tokenValue, rawCookieDomain) {\n const parts = [`crowdhandler=${tokenValue}`, 'path=/', 'Secure']\n if (rawCookieDomain) {\n const trimmed = String(rawCookieDomain).trim()\n if (/^\\.?[a-zA-Z0-9.-]+$/.test(trimmed)) {\n parts.push(`Domain=${trimmed}`)\n } else {\n console.warn(`[CH] Ignoring invalid COOKIE_DOMAIN value: ${JSON.stringify(rawCookieDomain)}`)\n }\n }\n return parts.join('; ')\n },\n queryStringParse: function(querystring) {\n const params = new URLSearchParams(querystring)\n let qStrObject = {}\n\n for (let item of params) {\n if (qStrObject.hasOwnProperty(item[0])) {\n if (Array.isArray(qStrObject[item[0]])) {\n qStrObject[item[0]].push(item[1])\n } else {\n qStrObject[item[0]] = [qStrObject[item[0]], item[1]]\n }\n } else {\n qStrObject[item[0]] = item[1]\n }\n }\n //return as object\n return qStrObject\n },\n}\n\nexport default helpers\n", "// Server error response (5xx, network errors) - respects failTrust setting\nconst dummyResponseData = {\n result: {\n status: 2,\n token: null,\n title: null,\n position: null,\n live_position: null,\n promoted: null,\n urlRedirect: null,\n onsale: null,\n message: null,\n slug: null,\n priority: null,\n priorityAvailable: null,\n logo: null,\n responseID: null,\n captchaRequired: null,\n ttl: null,\n },\n}\n\n// Client error response (4xx) - never triggers failTrust, always safety net\nconst clientErrorResponseData = {\n result: {\n status: 2,\n clientError: true,\n token: null,\n title: null,\n position: null,\n live_position: null,\n promoted: null,\n urlRedirect: null,\n onsale: null,\n message: null,\n slug: null,\n priority: null,\n priorityAvailable: null,\n logo: null,\n responseID: null,\n captchaRequired: null,\n ttl: null,\n },\n}\n\nconst http_helpers = {\n processResponse: async function(response) {\n let fetchResponse\n let responseObject = {}\n\n fetchResponse = await response\n\n //Communication failure. No fetch response to use.\n if (!fetchResponse) {\n responseObject.body = dummyResponseData\n responseObject.status = null\n responseObject.statusText = \"Communication failure between Cloudflare and the CrowdHandler API occurred.\"\n responseObject.success = false\n return responseObject;\n //Communication success. 4xx client error returned.\n } else if (fetchResponse.status >= 400 && fetchResponse.status < 500) {\n console.error(`[CH] API 4xx: ${fetchResponse.status}`)\n responseObject.body = clientErrorResponseData\n //Communication success. 5xx server error returned.\n } else if (fetchResponse.status >= 500) {\n console.error(`[CH] API 5xx: ${fetchResponse.status}`)\n responseObject.body = dummyResponseData\n //Normal response.\n } else {\n responseObject.body = await response.json()\n }\n\n responseObject.status = fetchResponse.status\n responseObject.statusText = fetchResponse.statusText\n responseObject.success = fetchResponse.ok\n\n return responseObject\n },\n}\n\nexport default http_helpers\n", "import helpers from './helpers/misc'\nimport http_helpers from './helpers/http'\nimport Timeout from 'await-timeout'\n\nasync function handleWhitelabelRequest(request, env) {\n let fallbackPath = `/${request.queryString}`\n let slug = request.path.substring(4)\n\n let templateContentType = 'text/html;charset=UTF-8'\n let templateDomain\n\n let devPublicKeys = [\n 'dba793b5eb837611498d0b809aefdefcb6f113310b272f6114435964670125a1',\n '04a39378b6abc3e3ee870828471636a9d1e157b1a7720821aed4c260108ebe43',\n ]\n\n if (devPublicKeys.includes(env.API_KEY)) {\n templateDomain = 'wait-dev.crowdhandler.com'\n } else {\n templateDomain = 'wait.crowdhandler.com'\n }\n\n let templateEndpoint\n let templateFetchTimeout = 6000\n if (slug) {\n templateEndpoint = `https://${templateDomain}/${slug}`\n } else {\n templateEndpoint = `https://${templateDomain}${fallbackPath}`\n }\n\n let cache = await caches.open('crowdhandler:cache')\n let cacheHit = await cache.match(templateEndpoint)\n\n if (cacheHit) {\n console.log('Serving waiting room template from cache.')\n return {\n response: cacheHit,\n useCache: true,\n }\n }\n\n let httpParams = {\n headers: {\n 'content-type': templateContentType,\n },\n method: 'GET',\n }\n\n async function gatherResponse(response) {\n const { headers } = response\n const contentType = headers.get('content-type') || ''\n if (contentType.includes('application/json')) {\n return JSON.stringify(await response.json())\n } else if (contentType.includes('application/text')) {\n return response.text()\n } else if (contentType.includes('text/html')) {\n return response.text()\n } else {\n return response.text()\n }\n }\n\n let errorState\n let fetchCounter = 0\n\n async function fetchTemplate() {\n let timer = new Timeout()\n //reset the error state\n errorState = null\n let response\n try {\n fetchCounter++\n response = await Promise.race([\n fetch(templateEndpoint, httpParams),\n timer.set(templateFetchTimeout, 'API Communication Timed Out!'),\n ])\n //await fetch(templateEndpoint, httpParams)\n if (response.status !== 200) {\n throw `${response.status} ${response.statusText}`\n }\n } catch (error) {\n errorState = true\n console.error('Template Fetch Failure:', error)\n } finally {\n timer.clear()\n if (errorState === true && fetchCounter < 3) {\n console.log('Retrying Template Fetch.')\n return await fetchTemplate()\n }\n return response\n }\n }\n\n let templateResponse = await fetchTemplate()\n let results\n let resultsMeta\n\n if (templateResponse) {\n results = await gatherResponse(templateResponse)\n resultsMeta = {\n headers: {\n 'content-type': templateContentType,\n },\n status: templateResponse.status,\n statusText: templateResponse.statusText,\n }\n } else {\n results = 'Service Temporarily Unavailable
'\n resultsMeta = {\n headers: {\n 'content-type': templateContentType,\n },\n status: 503,\n statusText: 'Service Unavailable',\n }\n }\n\n return { cache, results, resultsMeta, templateEndpoint }\n}\n\nasync function handleRequest(request, env, ctx) {\n\n //Log the time that the request was initiated\n const requestStartTime = Date.now()\n //Extensions that should be passed-through\n const bypassedFileExtensions = helpers.creativeAssetExtensions\n const wordpressExclusions = helpers.wordpressExclusions\n\n //Full URL\n const url = request.url\n const urlAttributes = new URL(url)\n //Hostname\n const host = urlAttributes.hostname\n //Don't try and queue static assets\n const path = urlAttributes.pathname\n //https://developers.cloudflare.com/workers/examples/logging-headers\n const requestHeaders = Object.fromEntries(request.headers)\n //https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-\n const unprocessedQueryString = urlAttributes.search\n //Allow customers behind an upstream proxy (eg. zScaler, Imperva) to source the\n //client IP from a different header. Defaults to Cloudflare's cf-connecting-ip.\n //For multi-value headers like x-forwarded-for, the left-most entry is used.\n //Any failure falls back to cf-connecting-ip so the worker never breaks.\n const fallbackIP = requestHeaders['cf-connecting-ip'] || null\n let IPAddress = fallbackIP\n try {\n if (env.IP_HEADER) {\n const overrideValue = requestHeaders[env.IP_HEADER.toLowerCase()]\n if (overrideValue) {\n const parsed = overrideValue.split(',')[0].trim()\n if (parsed) {\n IPAddress = parsed\n }\n }\n }\n } catch (error) {\n console.error('IP_HEADER override failed, falling back to cf-connecting-ip:', error)\n IPAddress = fallbackIP\n }\n const userAgent = requestHeaders['user-agent'] || null\n const validToken = /(.*\\d+.*)/\n let language = null\n let waitingRoomDomain\n\n let statusIdentifier = /^\\/ch\\/status$/\n let whiteLabelIdentifier = /^\\/ch\\/.*/\n\n //Check if the request is for a status check and handle response\n if (statusIdentifier.test(path) === true) {\n return new Response(\n JSON.stringify({ integration: 'cloudflare', status: 'ok' }),\n {\n headers: {\n 'content-type': 'text/plain',\n 'cache-control': 'public, max-age=60',\n },\n },\n )\n }\n\n //Check if the request is for a whitelabel waiting room and handle response\n if (whiteLabelIdentifier.test(path) === true) {\n //Handle the whitelabel request\n const whitelabelResponse = await handleWhitelabelRequest({\n path: path,\n queryString: unprocessedQueryString,\n }, env)\n\n //Return cached response if we have one.\n try {\n if (whitelabelResponse.useCache === true) {\n return whitelabelResponse.response\n }\n } catch (error) {\n console.error('Cache retrieval error:', error)\n }\n\n //Store template in cache\n try {\n whitelabelResponse.resultsMeta.headers['cache-control'] =\n 'public, max-age=60'\n\n if (whitelabelResponse.resultsMeta.status === 200) {\n await whitelabelResponse.cache.put(\n whitelabelResponse.templateEndpoint,\n new Response(\n whitelabelResponse.results,\n whitelabelResponse.resultsMeta,\n ),\n )\n }\n } catch (error) {\n console.error('Cache storage error:', error)\n }\n\n //Return the template\n return new Response(\n whitelabelResponse.results,\n whitelabelResponse.resultsMeta,\n )\n }\n\n //attempt to pull language from accept-language header\n try {\n language = requestHeaders['accept-language'].split(',')[0]\n } catch (error) {\n // Accept-language header not present - not critical\n }\n\n //Request object is read only so we are going to create a clone in order to be able to modify it\n const modifiedRequest = new Request(url, {\n body: request.body,\n headers: request.headers,\n method: request.method,\n redirect: request.redirect,\n })\n\n //We can't be sure that these optional environment variables exists so do a check first to avoid a reference error\n //Add x-ch-no-bypass header to request object if NO_BYPASS present in CF env variables\n if (env.NO_BYPASS) {\n modifiedRequest.headers.append('x-ch-no-bypass', env.NO_BYPASS)\n }\n\n //If environment variable is set to true, users that fail to check-in with CrowdHandler will be trusted.\n let failTrust = true\n if (env.FAIL_TRUST && env.FAIL_TRUST === 'false') {\n failTrust = false\n }\n\n //Set slug of fallback waiting room for users that fail to check-in with CrowdHandler.\n let safetyNetSlug\n if (env.SAFETY_NET_SLUG) {\n safetyNetSlug = env.SAFETY_NET_SLUG\n }\n\n //If environment variable is set to true, whitelabel waiting room will be used.\n let whitelabel = false\n if (env.WHITELABEL && env.WHITELABEL === 'true') {\n whitelabel = true\n }\n\n if (whitelabel === true) {\n waitingRoomDomain = `${host}/ch`\n } else {\n waitingRoomDomain = 'wait.crowdhandler.com'\n }\n\n //Handle static file extensions\n let fileExtension = path.match(/\\.([^.]+)$/)\n if (fileExtension !== null) {\n fileExtension = fileExtension[1]\n }\n\n if (bypassedFileExtensions.indexOf(fileExtension) !== -1) {\n return await fetch(modifiedRequest)\n }\n\n //Process query strings\n let queryString\n if (unprocessedQueryString) {\n queryString = helpers.queryStringParse(unprocessedQueryString)\n }\n\n //Destructure special params from query string if they are present\n let {\n 'ch-code': chCode,\n 'ch-fresh': chFresh,\n 'ch-id': chID,\n 'ch-id-signature': chIDSignature,\n 'ch-public-key': chPublicKey,\n 'ch-requested': chRequested,\n } = queryString || {}\n\n //Override chCode value if the current one is unusable\n if (!chCode || chCode === 'undefined' || chCode === 'null') {\n chCode = ''\n }\n\n //Remove special params from the queryString object now that we don't need them anymore\n if (queryString) {\n delete queryString['ch-code']\n delete queryString['ch-fresh']\n delete queryString['ch-id']\n delete queryString['ch-id-signature']\n delete queryString['ch-public-key']\n delete queryString['ch-requested']\n }\n\n //Convert to usable querystring format\n if (queryString && Object.keys(queryString).length !== 0) {\n let pairs = []\n for (const key of Object.keys(queryString)) {\n const values = Array.isArray(queryString[key]) ? queryString[key] : [queryString[key]]\n for (const val of values) {\n pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(val))\n }\n }\n\n queryString = `?${pairs.join('&')}`\n } else {\n queryString = null\n }\n\n //Handle Wordpress exclusions\n let origin_type\n if (env.ORIGIN_TYPE) {\n origin_type = env.ORIGIN_TYPE\n }\n\n if (origin_type === 'wordpress') {\n if (\n wordpressExclusions.test(path) === true ||\n wordpressExclusions.test(queryString) === true\n ) {\n return await fetch(modifiedRequest)\n }\n }\n\n //URL encode the targetURL to be used later in redirects\n let targetURL\n if (queryString) {\n targetURL = encodeURIComponent(`https://${host}${path}${queryString}`)\n } else {\n targetURL = encodeURIComponent(`https://${host}${path}`)\n }\n\n //Parse cookies\n const parsedCookies = helpers.parseCookies(requestHeaders)\n let crowdhandlerCookieValue = parsedCookies['crowdhandler']\n\n //Prioritise tokens in the ch-id parameter and fallback to ones found in the cookie\n let token\n let tokenSource\n let freshlyPromoted\n if (chID) {\n token = chID\n tokenSource = 'param'\n freshlyPromoted = true\n } else if (crowdhandlerCookieValue) {\n token = crowdhandlerCookieValue\n tokenSource = 'cookie'\n } else {\n token = null\n tokenSource = 'new'\n }\n\n //If this is a freshly promoted session, strip the special CrowdHandler parameters by issuing a redirect.\n if (freshlyPromoted) {\n let setCookie = {\n 'Set-Cookie': helpers.buildCrowdhandlerCookie(token, env.COOKIE_DOMAIN),\n }\n let redirectLocation\n if (queryString) {\n redirectLocation = { Location: `${path}${queryString}` }\n } else {\n redirectLocation = { Location: path }\n }\n return new Response(null, {\n status: 302,\n headers: Object.assign(\n helpers.noCacheHeaders,\n redirectLocation,\n setCookie,\n ),\n })\n }\n\n //Invalidate tokens that don't conform to the accepted format\n if (validToken.test(token) !== true) {\n token = null\n }\n\n //First API call here\n const apiHost = env.API_ENDPOINT\n const apiTimeout = 4000 // 4 second timeout\n let httpParams = {\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': env.API_KEY,\n },\n //choose method dynamically\n method: undefined,\n }\n\n //Determine if a GET or POST request should be made.\n let response\n let timer = new Timeout()\n\n //Make fetch\n if (token) {\n httpParams.method = 'GET'\n try {\n response = await Promise.race([\n fetch(\n `${apiHost}/requests/${token}?url=${targetURL}&agent=${encodeURIComponent(\n userAgent,\n )}&ip=${encodeURIComponent(IPAddress)}&lang=${encodeURIComponent(\n language,\n )}`,\n httpParams,\n ),\n timer.set(apiTimeout, 'CrowdHandler API request timed out'),\n ])\n } catch (error) {\n console.error('CrowdHandler API GET request failed:', error)\n response = undefined\n } finally {\n timer.clear()\n }\n } else {\n //This is a post so generate a payload and add it to the httpParams object\n httpParams.body = JSON.stringify({\n agent: userAgent,\n ip: IPAddress,\n lang: language,\n url: url,\n })\n httpParams.method = 'POST'\n try {\n response = await Promise.race([\n fetch(`${apiHost}/requests`, httpParams),\n timer.set(apiTimeout, 'CrowdHandler API request timed out'),\n ])\n } catch (error) {\n console.error('CrowdHandler API POST request failed:', error)\n response = undefined\n } finally {\n timer.clear()\n }\n }\n\n //Process fetch response\n const processResponse = http_helpers.processResponse\n const results = await processResponse(response)\n\n let responseBody\n\n //Handle API request error here\n if (results.success !== true) {\n console.error(\n `API error: ${results.status} ${results.statusText}`,\n )\n responseBody = results.body.result\n } else {\n responseBody = results.body.result\n }\n\n let redirect\n let redirectLocation\n let statusCode\n\n //Normal healthy response\n if (responseBody.promoted !== 1 && responseBody.status !== 2) {\n redirect = true\n redirectLocation = `https://${waitingRoomDomain}/${responseBody.slug}?url=${targetURL}&ch-code=${chCode}&ch-id=${responseBody.token}&ch-public-key=${env.API_KEY}`\n //4xx client error - always redirect to safety net (ignore failTrust)\n } else if (responseBody.clientError === true) {\n console.error('[CH] API returned 4xx client error - redirecting to safety net')\n redirect = true\n if (safetyNetSlug) {\n redirectLocation = `https://${waitingRoomDomain}/${safetyNetSlug}?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n } else {\n redirectLocation = `https://${waitingRoomDomain}/?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n }\n //5xx server error - respect failTrust setting\n } else if (\n failTrust !== true &&\n responseBody.promoted !== 1 &&\n responseBody.status === 2\n ) {\n redirect = true\n if (safetyNetSlug) {\n redirectLocation = `https://${waitingRoomDomain}/${safetyNetSlug}?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n } else {\n redirectLocation = `https://${waitingRoomDomain}/?url=${targetURL}&ch-code=${chCode}&ch-id=${token}&ch-public-key=${env.API_KEY}`\n }\n //User is promoted\n } else {\n redirect = false\n }\n\n switch (redirect) {\n case true: {\n console.log(`[CH] ${host}${path} | src:${tokenSource} | action:redirect | token:${responseBody.token || token || 'none'}`)\n if (responseBody.token) {\n return new Response(null, {\n status: 302,\n headers: Object.assign(helpers.noCacheHeaders, {\n Location: redirectLocation,\n 'Set-Cookie': helpers.buildCrowdhandlerCookie(responseBody.token, env.COOKIE_DOMAIN),\n }),\n })\n } else {\n return new Response(null, {\n status: 302,\n headers: Object.assign(helpers.noCacheHeaders, {\n Location: redirectLocation,\n }),\n })\n }\n break\n }\n case false: {\n console.log(`[CH] ${host}${path} | src:${tokenSource} | action:allow | token:${responseBody.token || 'none'}`)\n break\n }\n default: {\n break\n }\n }\n\n //We're dealing with the origin response from this point onwards\n const originResponse = await fetch(modifiedRequest)\n\n //Preserve original response but alter headers\n let modifiedOriginResponse = new Response(originResponse.body, {\n status: originResponse.status,\n statusText: originResponse.statusText,\n headers: originResponse.headers,\n })\n\n //Set token in cookie\n //Make sure we don't set invalid values\n if (validToken.test(responseBody.token) === true) {\n modifiedOriginResponse.headers.append(\n 'set-cookie',\n helpers.buildCrowdhandlerCookie(responseBody.token, env.COOKIE_DOMAIN),\n )\n }\n //Set integration method cookie\n modifiedOriginResponse.headers.append(\n 'set-cookie',\n `crowdhandler_integration=cloudflare; path=/; Secure`,\n )\n\n //End of request\n const requestEndTime = Date.now()\n\n //Send request Meta Data\n const responseID = responseBody.responseID\n\n //Send request meta information.\n async function sendRequestMeta() {\n //Sampling\n if (responseID && helpers.lottery(3) === 0) {\n httpParams.body = JSON.stringify({\n httpCode: originResponse.status,\n sampleRate: 3,\n time: requestEndTime - requestStartTime,\n })\n httpParams.method = 'PUT'\n response = await fetch(`${apiHost}/responses/${responseID}`, httpParams)\n\n const processResponse = http_helpers.processResponse\n const results = await processResponse(response)\n return results\n }\n }\n\n //This trick allows the sendRequestMeta function call to continue after we've already returned the response to the user\n //https://developers.cloudflare.com/workers/runtime-apis/context\n ctx.waitUntil(sendRequestMeta())\n\n //We're done send the response\n return modifiedOriginResponse\n}\n\nexport default {\n async fetch(request, env, ctx) {\n ctx.passThroughOnException()\n return await handleRequest(request, env, ctx)\n },\n}\n"],
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,YAAQ,iBAAiB,CAAC,SAAS,OAAO;AACxC,YAAM,UAAU,mCAAU;AACxB,WAAG;AACH,eAAO;AAAA,MACT,GAHgB;AAIhB,YAAM,QAAQ,8BAAK;AACjB,WAAG;AACH,eAAO,QAAQ,OAAO,CAAC;AAAA,MACzB,GAHc;AAId,aAAO,QAAQ,QAAQ,OAAO,EAAE,KAAK,SAAS,KAAK;AAAA,IACrD;AAOA,YAAQ,UAAU,WAAS;AACzB,cAAQ,OAAO,UAAU,aAAa,MAAM,IAAI;AAChD,aAAO,OAAO,UAAU,WAAW,IAAI,MAAM,KAAK,IAAI;AAAA,IACxD;AAAA;AAAA;;;ACpBA;AAAA;AAIA,QAAM,EAAC,gBAAgB,QAAO,IAAI;AAElC,WAAO,UAAU,MAAMA,SAAQ;AAAA,MAN/B,OAM+B;AAAA;AAAA;AAAA,MAC7B,OAAO,IAAI,OAAO,cAAc;AAC9B,eAAO,IAAIA,SAAQ,EAAE,IAAI,OAAO,YAAY;AAAA,MAC9C;AAAA,MAEA,OAAO,KAAK,SAAS,OAAO,cAAc;AACxC,eAAO,IAAIA,SAAQ,EAAE,KAAK,SAAS,OAAO,YAAY;AAAA,MACxD;AAAA,MAEA,cAAc;AACZ,aAAK,MAAM;AACX,aAAK,SAAS;AAAA,MAChB;AAAA,MAEA,IAAI,KAAK;AACP,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,IAAI,QAAQ;AACV,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,IAAI,OAAO,eAAe,IAAI;AAC5B,eAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,eAAK,MAAM;AACX,gBAAM,KAAK,eAAe,MAAM,OAAO,QAAQ,YAAY,CAAC,IAAI;AAChE,eAAK,MAAM,WAAW,IAAI,KAAK;AAC/B,eAAK,SAAS;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,MAEA,KAAK,SAAS,OAAO,eAAe,IAAI;AACtC,cAAM,iBAAiB,eAAe,SAAS,MAAM,KAAK,MAAM,CAAC;AACjE,cAAM,QAAQ,KAAK,IAAI,OAAO,YAAY;AAC1C,eAAO,QAAQ,KAAK;AAAA,UAClB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MAEA,QAAQ;AACN,YAAI,KAAK,KAAK;AACZ,uBAAa,KAAK,GAAG;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACnDA,IAAM,UAAU;AAAA;AAAA,EAEd,yBAAyB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAAA,EAEA,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,IACd,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAAA,EACA,SAAS,gCAAS,aAAa;AAC7B,WAAO,KAAK,MAAM,KAAK,OAAO,IAAI,SAAS,WAAW,CAAC;AAAA,EACzD,GAFS;AAAA,EAGT,cAAc,gCAAS,SAAS;AAC9B,UAAM,eAAe,CAAC;AACtB,QAAI,QAAQ,QAAQ;AAClB,cAAQ,OAAO,MAAM,GAAG,EAAE,QAAQ,YAAU;AAC1C,YAAI,QAAQ;AACV,gBAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,cAAI,MAAM,CAAC,MAAM,QAAW;AAC1B,yBAAa,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,EAAE,KAAK;AAAA,UAChD;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAbc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBd,yBAAyB,gCAAS,YAAY,iBAAiB;AAC7D,UAAM,QAAQ,CAAC,gBAAgB,UAAU,IAAI,UAAU,QAAQ;AAC/D,QAAI,iBAAiB;AACnB,YAAM,UAAU,OAAO,eAAe,EAAE,KAAK;AAC7C,UAAI,sBAAsB,KAAK,OAAO,GAAG;AACvC,cAAM,KAAK,UAAU,OAAO,EAAE;AAAA,MAChC,OAAO;AACL,gBAAQ,KAAK,8CAA8C,KAAK,UAAU,eAAe,CAAC,EAAE;AAAA,MAC9F;AAAA,IACF;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB,GAXyB;AAAA,EAYzB,kBAAkB,gCAAS,aAAa;AACtC,UAAM,SAAS,IAAI,gBAAgB,WAAW;AAC9C,QAAI,aAAa,CAAC;AAElB,aAAS,QAAQ,QAAQ;AACvB,UAAI,WAAW,eAAe,KAAK,CAAC,CAAC,GAAG;AACtC,YAAI,MAAM,QAAQ,WAAW,KAAK,CAAC,CAAC,CAAC,GAAG;AACtC,qBAAW,KAAK,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;AAAA,QAClC,OAAO;AACL,qBAAW,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;AAAA,QACrD;AAAA,MACF,OAAO;AACL,mBAAW,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC;AAAA,MAC9B;AAAA,IACF;AAEA,WAAO;AAAA,EACT,GAjBkB;AAkBpB;AAEA,IAAO,eAAQ;;;AC1Ff,IAAM,oBAAoB;AAAA,EACxB,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,IACV,eAAe;AAAA,IACf,UAAU;AAAA,IACV,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,KAAK;AAAA,EACP;AACF;AAGA,IAAM,0BAA0B;AAAA,EAC9B,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,IACV,eAAe;AAAA,IACf,UAAU;AAAA,IACV,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,KAAK;AAAA,EACP;AACF;AAEA,IAAM,eAAe;AAAA,EACnB,iBAAiB,sCAAe,UAAU;AACxC,QAAI;AACJ,QAAI,iBAAiB,CAAC;AAEtB,oBAAgB,MAAM;AAGtB,QAAI,CAAC,eAAe;AAClB,qBAAe,OAAO;AACtB,qBAAe,SAAS;AACxB,qBAAe,aAAa;AAC5B,qBAAe,UAAU;AACzB,aAAO;AAAA,IAET,WAAW,cAAc,UAAU,OAAO,cAAc,SAAS,KAAK;AACpE,cAAQ,MAAM,iBAAiB,cAAc,MAAM,EAAE;AACrD,qBAAe,OAAO;AAAA,IAExB,WAAW,cAAc,UAAU,KAAK;AACtC,cAAQ,MAAM,iBAAiB,cAAc,MAAM,EAAE;AACrD,qBAAe,OAAO;AAAA,IAExB,OAAO;AACL,qBAAe,OAAO,MAAM,SAAS,KAAK;AAAA,IAC5C;AAEA,mBAAe,SAAS,cAAc;AACtC,mBAAe,aAAa,cAAc;AAC1C,mBAAe,UAAU,cAAc;AAEvC,WAAO;AAAA,EACT,GA/BiB;AAgCnB;AAEA,IAAO,eAAQ;;;AC9Ef,2BAAoB;AAEpB,eAAe,wBAAwB,SAAS,KAAK;AACnD,MAAI,eAAe,IAAI,QAAQ,WAAW;AAC1C,MAAI,OAAO,QAAQ,KAAK,UAAU,CAAC;AAEnC,MAAI,sBAAsB;AAC1B,MAAI;AAEJ,MAAI,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,cAAc,SAAS,IAAI,OAAO,GAAG;AACvC,qBAAiB;AAAA,EACnB,OAAO;AACL,qBAAiB;AAAA,EACnB;AAEA,MAAI;AACJ,MAAI,uBAAuB;AAC3B,MAAI,MAAM;AACR,uBAAmB,WAAW,cAAc,IAAI,IAAI;AAAA,EACtD,OAAO;AACL,uBAAmB,WAAW,cAAc,GAAG,YAAY;AAAA,EAC7D;AAEA,MAAI,QAAQ,MAAM,OAAO,KAAK,oBAAoB;AAClD,MAAI,WAAW,MAAM,MAAM,MAAM,gBAAgB;AAEjD,MAAI,UAAU;AACZ,YAAQ,IAAI,2CAA2C;AACvD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,aAAa;AAAA,IACf,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA,QAAQ;AAAA,EACV;AAEA,iBAAe,eAAe,UAAU;AACtC,UAAM,EAAE,QAAQ,IAAI;AACpB,UAAM,cAAc,QAAQ,IAAI,cAAc,KAAK;AACnD,QAAI,YAAY,SAAS,kBAAkB,GAAG;AAC5C,aAAO,KAAK,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC7C,WAAW,YAAY,SAAS,kBAAkB,GAAG;AACnD,aAAO,SAAS,KAAK;AAAA,IACvB,WAAW,YAAY,SAAS,WAAW,GAAG;AAC5C,aAAO,SAAS,KAAK;AAAA,IACvB,OAAO;AACL,aAAO,SAAS,KAAK;AAAA,IACvB;AAAA,EACF;AAZe;AAcf,MAAI;AACJ,MAAI,eAAe;AAEnB,iBAAe,gBAAgB;AAC7B,QAAI,QAAQ,IAAI,qBAAAC,QAAQ;AAExB,iBAAa;AACb,QAAI;AACJ,QAAI;AACF;AACA,iBAAW,MAAM,QAAQ,KAAK;AAAA,QAC5B,MAAM,kBAAkB,UAAU;AAAA,QAClC,MAAM,IAAI,sBAAsB,8BAA8B;AAAA,MAChE,CAAC;AAED,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,GAAG,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MACjD;AAAA,IACF,SAAS,OAAO;AACd,mBAAa;AACb,cAAQ,MAAM,2BAA2B,KAAK;AAAA,IAChD,UAAE;AACA,YAAM,MAAM;AACZ,UAAI,eAAe,QAAQ,eAAe,GAAG;AAC3C,gBAAQ,IAAI,0BAA0B;AACtC,eAAO,MAAM,cAAc;AAAA,MAC7B;AACA,aAAO;AAAA,IACT;AAAA,EACF;AA1Be;AA4Bf,MAAI,mBAAmB,MAAM,cAAc;AAC3C,MAAI;AACJ,MAAI;AAEJ,MAAI,kBAAkB;AACpB,cAAU,MAAM,eAAe,gBAAgB;AAC/C,kBAAc;AAAA,MACZ,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ,iBAAiB;AAAA,MACzB,YAAY,iBAAiB;AAAA,IAC/B;AAAA,EACF,OAAO;AACL,cAAU;AACV,kBAAc;AAAA,MACZ,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR,YAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,aAAa,iBAAiB;AACzD;AAlHe;AAoHf,eAAe,cAAc,SAAS,KAAK,KAAK;AAG9C,QAAM,mBAAmB,KAAK,IAAI;AAElC,QAAM,yBAAyB,aAAQ;AACvC,QAAM,sBAAsB,aAAQ;AAGpC,QAAM,MAAM,QAAQ;AACpB,QAAM,gBAAgB,IAAI,IAAI,GAAG;AAEjC,QAAM,OAAO,cAAc;AAE3B,QAAM,OAAO,cAAc;AAE3B,QAAM,iBAAiB,OAAO,YAAY,QAAQ,OAAO;AAEzD,QAAM,yBAAyB,cAAc;AAK7C,QAAM,aAAa,eAAe,kBAAkB,KAAK;AACzD,MAAI,YAAY;AAChB,MAAI;AACF,QAAI,IAAI,WAAW;AACjB,YAAM,gBAAgB,eAAe,IAAI,UAAU,YAAY,CAAC;AAChE,UAAI,eAAe;AACjB,cAAM,SAAS,cAAc,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAChD,YAAI,QAAQ;AACV,sBAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,gEAAgE,KAAK;AACnF,gBAAY;AAAA,EACd;AACA,QAAM,YAAY,eAAe,YAAY,KAAK;AAClD,QAAM,aAAa;AACnB,MAAI,WAAW;AACf,MAAI;AAEJ,MAAI,mBAAmB;AACvB,MAAI,uBAAuB;AAG3B,MAAI,iBAAiB,KAAK,IAAI,MAAM,MAAM;AACxC,WAAO,IAAI;AAAA,MACT,KAAK,UAAU,EAAE,aAAa,cAAc,QAAQ,KAAK,CAAC;AAAA,MAC1D;AAAA,QACE,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,qBAAqB,KAAK,IAAI,MAAM,MAAM;AAE5C,UAAM,qBAAqB,MAAM,wBAAwB;AAAA,MACvD;AAAA,MACA,aAAa;AAAA,IACf,GAAG,GAAG;AAGN,QAAI;AACF,UAAI,mBAAmB,aAAa,MAAM;AACxC,eAAO,mBAAmB;AAAA,MAC5B;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,0BAA0B,KAAK;AAAA,IAC/C;AAGA,QAAI;AACF,yBAAmB,YAAY,QAAQ,eAAe,IACpD;AAEF,UAAI,mBAAmB,YAAY,WAAW,KAAK;AACjD,cAAM,mBAAmB,MAAM;AAAA,UAC7B,mBAAmB;AAAA,UACnB,IAAI;AAAA,YACF,mBAAmB;AAAA,YACnB,mBAAmB;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,wBAAwB,KAAK;AAAA,IAC7C;AAGA,WAAO,IAAI;AAAA,MACT,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,IACrB;AAAA,EACF;AAGA,MAAI;AACF,eAAW,eAAe,iBAAiB,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EAC3D,SAAS,OAAO;AAAA,EAEhB;AAGA,QAAM,kBAAkB,IAAI,QAAQ,KAAK;AAAA,IACvC,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,EACpB,CAAC;AAID,MAAI,IAAI,WAAW;AACjB,oBAAgB,QAAQ,OAAO,kBAAkB,IAAI,SAAS;AAAA,EAChE;AAGA,MAAI,YAAY;AAChB,MAAI,IAAI,cAAc,IAAI,eAAe,SAAS;AAChD,gBAAY;AAAA,EACd;AAGA,MAAI;AACJ,MAAI,IAAI,iBAAiB;AACvB,oBAAgB,IAAI;AAAA,EACtB;AAGA,MAAI,aAAa;AACjB,MAAI,IAAI,cAAc,IAAI,eAAe,QAAQ;AAC/C,iBAAa;AAAA,EACf;AAEA,MAAI,eAAe,MAAM;AACvB,wBAAoB,GAAG,IAAI;AAAA,EAC7B,OAAO;AACL,wBAAoB;AAAA,EACtB;AAGA,MAAI,gBAAgB,KAAK,MAAM,YAAY;AAC3C,MAAI,kBAAkB,MAAM;AAC1B,oBAAgB,cAAc,CAAC;AAAA,EACjC;AAEA,MAAI,uBAAuB,QAAQ,aAAa,MAAM,IAAI;AACxD,WAAO,MAAM,MAAM,eAAe;AAAA,EACpC;AAGA,MAAI;AACJ,MAAI,wBAAwB;AAC1B,kBAAc,aAAQ,iBAAiB,sBAAsB;AAAA,EAC/D;AAGA,MAAI;AAAA,IACF,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,EAClB,IAAI,eAAe,CAAC;AAGpB,MAAI,CAAC,UAAU,WAAW,eAAe,WAAW,QAAQ;AAC1D,aAAS;AAAA,EACX;AAGA,MAAI,aAAa;AACf,WAAO,YAAY,SAAS;AAC5B,WAAO,YAAY,UAAU;AAC7B,WAAO,YAAY,OAAO;AAC1B,WAAO,YAAY,iBAAiB;AACpC,WAAO,YAAY,eAAe;AAClC,WAAO,YAAY,cAAc;AAAA,EACnC;AAGA,MAAI,eAAe,OAAO,KAAK,WAAW,EAAE,WAAW,GAAG;AACxD,QAAI,QAAQ,CAAC;AACb,eAAW,OAAO,OAAO,KAAK,WAAW,GAAG;AAC1C,YAAM,SAAS,MAAM,QAAQ,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,IAAI,CAAC,YAAY,GAAG,CAAC;AACrF,iBAAW,OAAO,QAAQ;AACxB,cAAM,KAAK,mBAAmB,GAAG,IAAI,MAAM,mBAAmB,GAAG,CAAC;AAAA,MACpE;AAAA,IACF;AAEA,kBAAc,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EACnC,OAAO;AACL,kBAAc;AAAA,EAChB;AAGA,MAAI;AACJ,MAAI,IAAI,aAAa;AACnB,kBAAc,IAAI;AAAA,EACpB;AAEA,MAAI,gBAAgB,aAAa;AAC/B,QACE,oBAAoB,KAAK,IAAI,MAAM,QACnC,oBAAoB,KAAK,WAAW,MAAM,MAC1C;AACA,aAAO,MAAM,MAAM,eAAe;AAAA,IACpC;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,aAAa;AACf,gBAAY,mBAAmB,WAAW,IAAI,GAAG,IAAI,GAAG,WAAW,EAAE;AAAA,EACvE,OAAO;AACL,gBAAY,mBAAmB,WAAW,IAAI,GAAG,IAAI,EAAE;AAAA,EACzD;AAGA,QAAM,gBAAgB,aAAQ,aAAa,cAAc;AACzD,MAAI,0BAA0B,cAAc,cAAc;AAG1D,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,MAAM;AACR,YAAQ;AACR,kBAAc;AACd,sBAAkB;AAAA,EACpB,WAAW,yBAAyB;AAClC,YAAQ;AACR,kBAAc;AAAA,EAChB,OAAO;AACL,YAAQ;AACR,kBAAc;AAAA,EAChB;AAGA,MAAI,iBAAiB;AACnB,QAAI,YAAY;AAAA,MACd,cAAc,aAAQ,wBAAwB,OAAO,IAAI,aAAa;AAAA,IACxE;AACA,QAAIC;AACJ,QAAI,aAAa;AACf,MAAAA,oBAAmB,EAAE,UAAU,GAAG,IAAI,GAAG,WAAW,GAAG;AAAA,IACzD,OAAO;AACL,MAAAA,oBAAmB,EAAE,UAAU,KAAK;AAAA,IACtC;AACA,WAAO,IAAI,SAAS,MAAM;AAAA,MACxB,QAAQ;AAAA,MACR,SAAS,OAAO;AAAA,QACd,aAAQ;AAAA,QACRA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,MAAI,WAAW,KAAK,KAAK,MAAM,MAAM;AACnC,YAAQ;AAAA,EACV;AAGA,QAAM,UAAU,IAAI;AACpB,QAAM,aAAa;AACnB,MAAI,aAAa;AAAA,IACf,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,aAAa,IAAI;AAAA,IACnB;AAAA;AAAA,IAEA,QAAQ;AAAA,EACV;AAGA,MAAI;AACJ,MAAI,QAAQ,IAAI,qBAAAD,QAAQ;AAGxB,MAAI,OAAO;AACT,eAAW,SAAS;AACpB,QAAI;AACF,iBAAW,MAAM,QAAQ,KAAK;AAAA,QAC5B;AAAA,UACE,GAAG,OAAO,aAAa,KAAK,QAAQ,SAAS,UAAU;AAAA,YACrD;AAAA,UACF,CAAC,OAAO,mBAAmB,SAAS,CAAC,SAAS;AAAA,YAC5C;AAAA,UACF,CAAC;AAAA,UACD;AAAA,QACF;AAAA,QACA,MAAM,IAAI,YAAY,oCAAoC;AAAA,MAC5D,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,wCAAwC,KAAK;AAC3D,iBAAW;AAAA,IACb,UAAE;AACA,YAAM,MAAM;AAAA,IACd;AAAA,EACF,OAAO;AAEL,eAAW,OAAO,KAAK,UAAU;AAAA,MAC/B,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AACD,eAAW,SAAS;AACpB,QAAI;AACF,iBAAW,MAAM,QAAQ,KAAK;AAAA,QAC5B,MAAM,GAAG,OAAO,aAAa,UAAU;AAAA,QACvC,MAAM,IAAI,YAAY,oCAAoC;AAAA,MAC5D,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAyC,KAAK;AAC5D,iBAAW;AAAA,IACb,UAAE;AACA,YAAM,MAAM;AAAA,IACd;AAAA,EACF;AAGA,QAAM,kBAAkB,aAAa;AACrC,QAAM,UAAU,MAAM,gBAAgB,QAAQ;AAE9C,MAAI;AAGJ,MAAI,QAAQ,YAAY,MAAM;AAC5B,YAAQ;AAAA,MACN,cAAc,QAAQ,MAAM,IAAI,QAAQ,UAAU;AAAA,IACpD;AACA,mBAAe,QAAQ,KAAK;AAAA,EAC9B,OAAO;AACL,mBAAe,QAAQ,KAAK;AAAA,EAC9B;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI;AAGJ,MAAI,aAAa,aAAa,KAAK,aAAa,WAAW,GAAG;AAC5D,eAAW;AACX,uBAAmB,WAAW,iBAAiB,IAAI,aAAa,IAAI,QAAQ,SAAS,YAAY,MAAM,UAAU,aAAa,KAAK,kBAAkB,IAAI,OAAO;AAAA,EAElK,WAAW,aAAa,gBAAgB,MAAM;AAC5C,YAAQ,MAAM,gEAAgE;AAC9E,eAAW;AACX,QAAI,eAAe;AACjB,yBAAmB,WAAW,iBAAiB,IAAI,aAAa,QAAQ,SAAS,YAAY,MAAM,UAAU,KAAK,kBAAkB,IAAI,OAAO;AAAA,IACjJ,OAAO;AACL,yBAAmB,WAAW,iBAAiB,SAAS,SAAS,YAAY,MAAM,UAAU,KAAK,kBAAkB,IAAI,OAAO;AAAA,IACjI;AAAA,EAEF,WACE,cAAc,QACd,aAAa,aAAa,KAC1B,aAAa,WAAW,GACxB;AACA,eAAW;AACX,QAAI,eAAe;AACjB,yBAAmB,WAAW,iBAAiB,IAAI,aAAa,QAAQ,SAAS,YAAY,MAAM,UAAU,KAAK,kBAAkB,IAAI,OAAO;AAAA,IACjJ,OAAO;AACL,yBAAmB,WAAW,iBAAiB,SAAS,SAAS,YAAY,MAAM,UAAU,KAAK,kBAAkB,IAAI,OAAO;AAAA,IACjI;AAAA,EAEF,OAAO;AACL,eAAW;AAAA,EACb;AAEA,UAAQ,UAAU;AAAA,IAChB,KAAK,MAAM;AACT,cAAQ,IAAI,QAAQ,IAAI,GAAG,IAAI,UAAU,WAAW,8BAA8B,aAAa,SAAS,SAAS,MAAM,EAAE;AACzH,UAAI,aAAa,OAAO;AACtB,eAAO,IAAI,SAAS,MAAM;AAAA,UACxB,QAAQ;AAAA,UACR,SAAS,OAAO,OAAO,aAAQ,gBAAgB;AAAA,YAC7C,UAAU;AAAA,YACV,cAAc,aAAQ,wBAAwB,aAAa,OAAO,IAAI,aAAa;AAAA,UACrF,CAAC;AAAA,QACH,CAAC;AAAA,MACH,OAAO;AACL,eAAO,IAAI,SAAS,MAAM;AAAA,UACxB,QAAQ;AAAA,UACR,SAAS,OAAO,OAAO,aAAQ,gBAAgB;AAAA,YAC7C,UAAU;AAAA,UACZ,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,cAAQ,IAAI,QAAQ,IAAI,GAAG,IAAI,UAAU,WAAW,2BAA2B,aAAa,SAAS,MAAM,EAAE;AAC7G;AAAA,IACF;AAAA,IACA,SAAS;AACP;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,MAAM,MAAM,eAAe;AAGlD,MAAI,yBAAyB,IAAI,SAAS,eAAe,MAAM;AAAA,IAC7D,QAAQ,eAAe;AAAA,IACvB,YAAY,eAAe;AAAA,IAC3B,SAAS,eAAe;AAAA,EAC1B,CAAC;AAID,MAAI,WAAW,KAAK,aAAa,KAAK,MAAM,MAAM;AAChD,2BAAuB,QAAQ;AAAA,MAC7B;AAAA,MACA,aAAQ,wBAAwB,aAAa,OAAO,IAAI,aAAa;AAAA,IACvE;AAAA,EACF;AAEA,yBAAuB,QAAQ;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AAGA,QAAM,iBAAiB,KAAK,IAAI;AAGhC,QAAM,aAAa,aAAa;AAGhC,iBAAe,kBAAkB;AAE/B,QAAI,cAAc,aAAQ,QAAQ,CAAC,MAAM,GAAG;AAC1C,iBAAW,OAAO,KAAK,UAAU;AAAA,QAC/B,UAAU,eAAe;AAAA,QACzB,YAAY;AAAA,QACZ,MAAM,iBAAiB;AAAA,MACzB,CAAC;AACD,iBAAW,SAAS;AACpB,iBAAW,MAAM,MAAM,GAAG,OAAO,cAAc,UAAU,IAAI,UAAU;AAEvE,YAAME,mBAAkB,aAAa;AACrC,YAAMC,WAAU,MAAMD,iBAAgB,QAAQ;AAC9C,aAAOC;AAAA,IACT;AAAA,EACF;AAfe;AAmBf,MAAI,UAAU,gBAAgB,CAAC;AAG/B,SAAO;AACT;AAjde;AAmdf,IAAO,gBAAQ;AAAA,EACb,MAAM,MAAM,SAAS,KAAK,KAAK;AAC7B,QAAI,uBAAuB;AAC3B,WAAO,MAAM,cAAc,SAAS,KAAK,GAAG;AAAA,EAC9C;AACF;",
"names": ["Timeout", "Timeout", "redirectLocation", "processResponse", "results"]
}
diff --git a/index.js b/index.js
index 16ef5e0..e14182e 100644
--- a/index.js
+++ b/index.js
@@ -137,7 +137,26 @@ async function handleRequest(request, env, ctx) {
const requestHeaders = Object.fromEntries(request.headers)
//https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
const unprocessedQueryString = urlAttributes.search
- const IPAddress = requestHeaders['cf-connecting-ip'] || null
+ //Allow customers behind an upstream proxy (eg. zScaler, Imperva) to source the
+ //client IP from a different header. Defaults to Cloudflare's cf-connecting-ip.
+ //For multi-value headers like x-forwarded-for, the left-most entry is used.
+ //Any failure falls back to cf-connecting-ip so the worker never breaks.
+ const fallbackIP = requestHeaders['cf-connecting-ip'] || null
+ let IPAddress = fallbackIP
+ try {
+ if (env.IP_HEADER) {
+ const overrideValue = requestHeaders[env.IP_HEADER.toLowerCase()]
+ if (overrideValue) {
+ const parsed = overrideValue.split(',')[0].trim()
+ if (parsed) {
+ IPAddress = parsed
+ }
+ }
+ }
+ } catch (error) {
+ console.error('IP_HEADER override failed, falling back to cf-connecting-ip:', error)
+ IPAddress = fallbackIP
+ }
const userAgent = requestHeaders['user-agent'] || null
const validToken = /(.*\d+.*)/
let language = null