Last active
January 17, 2025 14:16
-
-
Save hutt/7b3c254a995849e6a06709a872840685 to your computer and use it in GitHub Desktop.
This Cloudflare Worker proxies and caches requests to a CDN, making it easier to avoid third-party-requests
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
// This Cloudflare Worker proxies and caches requests to a CDN, making it easier to avoid third-party-requests | |
// https://gist.github.com/hutt/7b3c254a995849e6a06709a872840685/ | |
// Base URL for JSDelivr CDN | |
const JSDELIVR_BASE_URL = 'https://cdn.jsdelivr.net'; | |
// Path prefix for our proxy | |
const PROXY_PATH = '/cdn-jsdelivr'; | |
// Default cache duration in seconds (6 hours) | |
const DEFAULT_CACHE_DURATION = 6 * 60 * 60; | |
// Listen for incoming fetch events | |
addEventListener('fetch', event => { | |
event.respondWith(handleRequest(event)); | |
}); | |
async function handleRequest(event) { | |
try { | |
const request = event.request; | |
// Parse the request URL | |
const url = new URL(request.url); | |
// Optimized URL processing | |
const path = url.pathname; | |
if (path.startsWith(PROXY_PATH)) { | |
const jsdelivrPath = path.slice(PROXY_PATH.length); | |
// Construct the full JSDelivr URL | |
const jsdelivrUrl = `${JSDELIVR_BASE_URL}${jsdelivrPath}`; | |
// Try to get the response from cache first | |
const cache = caches.default; | |
let response = await cache.match(request); | |
if (!response) { | |
// If not in cache, fetch the resource from JSDelivr | |
response = await fetch(jsdelivrUrl, { | |
// Forward the original request headers, method, and body | |
headers: request.headers, | |
method: request.method, | |
body: request.body, | |
}); | |
// Clone the response before caching it | |
const responseToCache = response.clone(); | |
// Create new response with custom cache control header | |
const newResponse = new Response(responseToCache.body, responseToCache); | |
// Implement stale-while-revalidate caching | |
newResponse.headers.set('Cache-Control', `public, max-age=${DEFAULT_CACHE_DURATION}, stale-while-revalidate=${DEFAULT_CACHE_DURATION}`); | |
// Set ETag header | |
newResponse.headers.set('ETag', response.headers.get('ETag') || crypto.randomUUID()); | |
// Set Content-Encoding header | |
newResponse.headers.set('Content-Encoding', response.headers.get('Content-Encoding') || 'gzip'); | |
// Put the response in cache | |
event.waitUntil(cache.put(request, newResponse)); | |
} | |
return response; | |
} | |
// If the path doesn't start with our proxy path, return a 404 | |
return new Response('Not Found', { status: 404 }); | |
} catch (error) { | |
// Improved error handling | |
return new Response(`Error: ${error.message}`, { status: 500 }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment