Skip to content

Instantly share code, notes, and snippets.

@hutt
Last active January 17, 2025 14:16
Show Gist options
  • Save hutt/7b3c254a995849e6a06709a872840685 to your computer and use it in GitHub Desktop.
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 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