Last active
September 28, 2022 22:26
-
-
Save bcnzer/c1f2008099ff9599d12a915ddec712ed to your computer and use it in GitHub Desktop.
Example of a Cloudflare Worker and Worker KV storage used to transfer/migrate traffic to alternatively infrastructure
This file contains 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.passThroughOnException() | |
event.respondWith(handleRequest(event.request)) | |
}) | |
async function handleRequest(request) { | |
const maxBizId = await MIGRATION_SETTINGS.get('maxbizid') | |
const currentBusinessId = getBusinessIdFromCookie(request) | |
if (!maxBizId || maxBizId == 0 || !currentBusinessId) { | |
return await fetch(request) | |
} | |
const isTestBiz = await businessInKey(currentBusinessId, 'testbizids') | |
if (isTestBiz) { | |
// They're whitelisted as a test business so redirect them | |
return await redirect(request) | |
} | |
const isException = await businessInKey(currentBusinessId, 'bizidexceptions') | |
if (!isException && Number(currentBusinessId) <= Number(maxBizId)) { | |
// This biz is under the current max and is not an exception (i.e. VIPs) so redirect it | |
return await redirect(request) | |
} | |
return await fetch(request) | |
} | |
function getBusinessIdFromCookie(request) { | |
if (!request.headers) return null | |
let bizId = null | |
const cookies = request.headers.get('Cookie') || "" | |
if (cookies.includes(';')) { | |
// There's multiple cookies | |
const splitCookies = cookies.split(';') | |
splitCookies.forEach(cookie => { | |
if (cookie.includes('t-business')) { | |
bizId = cookie.split('=')[1] | |
} | |
}) | |
} else { | |
if (cookies.includes('t-business')) { | |
bizId = cookie.split('=')[1] | |
} | |
} | |
return bizId | |
} | |
async function businessInKey(bizId, keyName) { | |
if (!bizId || bizId == 0) { | |
return false | |
} | |
const ids = await MIGRATION_SETTINGS.get(keyName) | |
return ids.split(',').indexOf(bizId.toString()) > -1 | |
} | |
function requiresRewritingLinks(request, response){ | |
// Change the string below to match whatever you need | |
return request.url.includes('[entermypartialurlstringhere]') && | |
response.headers.get("Content-Type").includes("application/json") | |
} | |
async function rewriteResponseBody(response, target, replacement){ | |
let bodyText = await response.text() | |
bodyText = bodyText.replace(new RegExp(target, 'g'), replacement) | |
return new Response(bodyText, { | |
headers: response.headers | |
}) | |
} | |
async function redirect(request){ | |
try { | |
const originalHost = 'app.myurl.com' // enter original URL here | |
const redirectHost = 'myapp.azurewebsites.net' // enter URL of what you're redirecting to | |
const redirectUrl = request.url.replace(originalHost, redirectHost) | |
let init = { | |
method: request.method, | |
headers: request.headers, | |
body: request.body, | |
redirect : "manual" // The stupidly important redirect parameter | |
} | |
let response = await fetch(new Request(redirectUrl, init)) | |
if(requiresRewritingLinks(request, response)){ | |
response = await rewriteResponseBody(response, redirectHost, originalHost) | |
} | |
let finalResponse = new Response(response.body, response) | |
finalResponse.headers.set('t-redirected', 'true') // Flag we added so it was clear your response was redirected | |
return finalResponse | |
} catch (e) { | |
return new Response(e) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment