-
-
Save Dexus/b936106b8313cb8c1f51dcc03ef9781d to your computer and use it in GitHub Desktop.
Handmade load balancer for Cloudflare Workers
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
const europe = ["AMS", "ATH", "BCN", "BEG", "TXL", "BRU", "OTP", "BUD", "KIV", "CPH", "DUB", "DUS", "EDI", "FRA", "GVA", "GOT", "HAM", "HEL", "IST", "KBP", "LIS", "LHR", "LUX", "MAD", "MAN", "MRS", "MXP", "DME", "MUC", "LCA", "OSL", "CDG", "PRG", "KEF", "RIX", "FCO", "LED", "SOF", "ARN", "TLL", "SKG", "VIE", "VNO", "WAW", "ZAG", "ZRH"]; | |
const africa = ["CAI", "CMN", "CPT", "DAR", "JIB", "DUR", "JNB", "LOS", "LAD", "MPM", "MBA", "MRU", "RUN", "KGL"]; | |
const asia = ["BKK", "CEB", "CTU", "MAA", "CMB", "SZX", "FUO", "FOC", "CAN", "HGH", "HAN", "HNY", "SGN", "HKG", "HYD", "ISB", "TNA", "KHI", "KTM", "KUL", "LHE", "NAY", "LYA", "MFM", "MNL", "BOM", "NNG", "DEL", "KIX", "PNH", "TAO", "ICN", "SHA", "SHE", "SJW", "SIN", "SZV", "TPE", "TSN", "NRT", "ULN", "WUH", "WUX", "XIY", "EVN", "CGO", "CSX"]; | |
const latinAmerica = ["ASU", "BOG", "EZE", "CWB", "FOR", "LIM", "MDE", "MEX", "PTY", "POA", "UIO", "GIG", "GRU", "SCL", "CUR"]; | |
const middleEast = ["AMM", "BGW", "GYD", "BEY", "DOH", "DXB", "KWI", "BAH", "MCT", "ZDM", "RUH", "TLV"]; | |
const northAmerica = ["IAD", "ATL", "BOS", "BUF", "YYC", "CLT", "ORD", "CMH", "DFW", "DEN", "DTW", "IAH", "IND", "JAX", "MCI", "LAS", "LAX", "MFE", "MEM", "MIA", "MSP", "MGM", "YUL", "BNA", "EWR", "ORF", "OMA", "PHX", "PIT", "PDX", "QRO", "RIC", "SMF", "SLC", "SAN", "SJC", "YXE", "SEA", "STL", "TPA", "YYZ", "YVR", "TLH", "YWG"]; | |
const oceania = ["AKL", "BNE", "MEL", "PER", "SYD"] | |
const euroApi = "europe-west1-XXXXXX.cloudfunctions.net"; | |
const usApi = "us-central1-XXXXXX.cloudfunctions.net"; | |
const asiaApi = "asia-east2-XXXXXX.cloudfunctions.net"; | |
addEventListener('fetch', event => { | |
// A promise is required | |
event.respondWith(eventHandler(event)) | |
}) | |
async function eventHandler(event){ | |
let hostname = matchGeo(event.request.cf ? event.request.cf.colo : "BRU") // the "cf" object is not accessible in the Playground | |
return await fetch(genRequest(event.request, hostname)).then((response) => { | |
if (response.status < 400) // If OK or redirect | |
return response; | |
else throw new Error(response.status + " " + hostname); | |
}).catch(async (err) => { | |
// In case of issues, try another host | |
console.error(err); | |
return await fetch(genRequest(event.request, getBackupHost(hostname))).then((response) => { | |
console.log(response); | |
if (response.status < 400) // if OK or redirect | |
return response; | |
else throw new Error(response.status); | |
}).catch((err) => { | |
console.error(err) | |
return new Response(null, {status: 500}); // We're giving up | |
}); | |
}); | |
} | |
function matchGeo(colo) { | |
if (europe.includes(colo)) | |
return euroApi; | |
else if (africa.includes(colo)) | |
return euroApi; | |
else if (asia.includes(colo)) | |
return asiaApi; | |
else if (latinAmerica.includes(colo)) | |
return usApi; | |
else if (middleEast.includes(colo)) | |
return euroApi; | |
else if (northAmerica.includes(colo)) | |
return usApi; | |
else | |
return asiaApi; | |
} | |
function getBackupHost(hostname) { | |
switch(hostname){ | |
case usApi: | |
return euroApi; | |
default: | |
return usApi; | |
} | |
} | |
function genRequest(request, hostname) { | |
let url = new URL(request.url) | |
url.hostname = hostname | |
return new Request(url, request) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment