Skip to content

Instantly share code, notes, and snippets.

@shagamemnon
Last active September 16, 2019 05:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shagamemnon/aa0b3ffdddcdc8395792f4d038bef23b to your computer and use it in GitHub Desktop.
Save shagamemnon/aa0b3ffdddcdc8395792f4d038bef23b to your computer and use it in GitHub Desktop.
A Cloudflare Worker for session persistence
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
event.passThroughOnException()
})
const ORIGINS = [
'storage.googleapis.com',
'frank-io.herokuapp.com'
]
class StickySession {
constructor (request) {
this.request = new Request(request)
this.url = new URL(this.request.url)
this.hdrs = new Headers(this.request.headers)
this.clientCookie = {}
if (this.hdrs.has('cookie')) {
this.clientCookie = new URLSearchParams(this.hdrs.get('cookie').trim().split(';').join('&'))
} else {
this.clientCookie = new URLSearchParams('_lbid=null')
}
this.origin = null
this.intercept = false
this.domainParam = this.url.hostname.split('.').splice(-2,2).join('.')
console.log(this)
}
// probably overkill to use SHA-1
static async digest (msg) {
const msgUint8 = new TextEncoder().encode(msg)
const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
return hashHex
}
get sticker () {
return this.origin
}
set sticker (param) {
if (this.clientCookie.has(param) && this.clientCookie.get(param) != 'null') {
this.origin = this.clientCookie.get(param)
console.log(this.origin)
} else {
const random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
const originToHash = ORIGINS[random(0, ORIGINS.length - 1)]
this.intercept = true
this.origin = StickySession.digest(originToHash)
}
}
async selectOrigin () {
for (let i = 0; i < ORIGINS.length; i++) {
let server = await StickySession.digest(ORIGINS[i])
if (server === await this.sticker) {
console.log(server, this.sticker, ORIGINS[i])
return ORIGINS[i]
}
}
}
}
async function handleRequest (request) {
let session = new StickySession(request)
// session.sticker is the cookie parameter key name
session.sticker = '_lbid'
// reassign the hostname property only.
session.url.hostname = await session.selectOrigin()
let response = await fetch(session.url, session.request)
response = new Response(response.body, response)
// TODO - move intercept boolean into class definitiion
if (!session.intercept) return response
// optionally set domain name parameter. Be sure to including the "." prefix for subdomains
response.headers.append('set-cookie', `_lbid=${await session.sticker}; domain=.${session.domainParam};`)
return response
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment