-
-
Save etdev/bb49f0f60ea5ec9deb5977b1fbfb4046 to your computer and use it in GitHub Desktop.
| 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!
Do you know how can I configure algoliasearch.js to use the proxy?
Hi everyone! 👋
If you're looking for a slightly more expanded version of this setup, I've put together a full repository based on a similar concept here: MarcinKilarski/algolia-caching-proxy-via-cloudflare-worker
It includes a complete Cloudflare Worker project structure, built-in security features (like CORS and domain whitelisting), and a detailed README with step-by-step instructions on how to set it up (including how to configure the frontend Algolia client to use the proxy).
Huge thanks to @etdev for the original gist and inspiration! Feel free to check out the repo if it helps with your use case.
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: DYNAMICand showing hits in the Algolia API logs repeated requests. Did you have to do anything else to get the cached response to return ?Thanks!