Last active
March 24, 2025 09:00
-
-
Save etdev/bb49f0f60ea5ec9deb5977b1fbfb4046 to your computer and use it in GitHub Desktop.
Algolia cache proxy - 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
const ALGOLIA_APP_ID = "<your algolia app id>"; | |
addEventListener('fetch', event => { | |
try { | |
const request = event.request; | |
if (request.method.toUpperCase() === 'POST') return event.respondWith(handlePostRequest(event)); | |
return handleRequest(request); | |
} catch (e) { | |
return event.respondWith(new Response('Error thrown ' + e.message)); | |
} | |
}); | |
async function handleRequest(request) { | |
const algoliaUrl = new URL(request.url); | |
algoliaUrl.host = `${ALGOLIA_APP_ID}-dsn.algolia.net`; | |
const algoliaRequest = new Request(algoliaUrl, { | |
body: request.body, | |
headers: request.headers, | |
method: request.method, | |
redirect: request.redirect | |
}); | |
let response = await fetch(algoliaRequest); | |
// Reconstruct the Response object to make its headers mutable. | |
response = new Response(response.body, response); | |
response.headers.delete("cache-control"); | |
response.headers.set("Access-Control-ALlow-Origin", "*"); | |
response.headers.set("Access-Control-ALlow-Methods", "GET,HEAD,POST,OPTIONS"); | |
return response; | |
} | |
// post caching | |
async function handlePostRequest(event) { | |
const request = event.request; | |
const dupRequest = request.clone(); | |
// assumes JSON body | |
const body = await dupRequest.json(); | |
// Hash the request body to use it as a part of the cache key | |
const hash = await sha256(JSON.stringify(body)); | |
const cacheUrl = new URL(request.url); | |
// Store the URL in cache by prepending the body's hash | |
cacheUrl.pathname = '/posts' + cacheUrl.pathname + hash; | |
// Convert to a GET to be able to cache | |
const cacheKey = new Request(cacheUrl.toString(), { | |
headers: request.headers, | |
method: 'GET', | |
}); | |
const cache = caches.default; | |
// Find the cache key in the cache | |
let response = await cache.match(cacheKey); | |
// if not in cache, fetch response to POST request from origin + cache it | |
if (!response) { | |
response = await handleRequest(request); | |
event.waitUntil(cache.put(cacheKey, response.clone())); | |
} | |
return response; | |
} | |
async function sha256(message) { | |
// encode as UTF-8 | |
const msgBuffer = new TextEncoder().encode(message); | |
// hash the message | |
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); | |
// convert bytes to hex string | |
return [...new Uint8Array(hashBuffer)].map(b => b.toString(16).padStart(2, '0')).join(''); | |
} |
Actually looks like it's working. I must not have been patient enough with the rollout of the worker. Thanks for putting this together and sharing!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @etdev
I was writing something similar and came across your gist. In my case, it processes the request, but I'm still getting
CF-Cache-Status: DYNAMIC
and showing hits in the Algolia API logs repeated requests. Did you have to do anything else to get the cached response to return ?Thanks!