Add index.js
This commit is contained in:
parent
8bf1693cc0
commit
9228c5ee4e
136
index.js
Normal file
136
index.js
Normal file
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Cloudflare Worker to cache a URL on all US Edge servers
|
||||
*
|
||||
* This worker:
|
||||
* 1. Accepts a target URL via query parameter or POST body
|
||||
* 2. Fetches the URL using Cloudflare's fetch API
|
||||
* 3. Forces caching by setting appropriate cache headers
|
||||
* 4. Can be configured to cache on specific US regions or all of them
|
||||
*/
|
||||
|
||||
// Define US Cloudflare regions (These are the major US colo locations)
|
||||
const US_REGIONS = [
|
||||
"IAD", // Washington DC (Northern Virginia)
|
||||
"EWR", // Newark, NJ
|
||||
"ATL", // Atlanta, GA
|
||||
"MIA", // Miami, FL
|
||||
"ORD", // Chicago, IL
|
||||
"DFW", // Dallas, TX
|
||||
"DEN", // Denver, CO
|
||||
"SEA", // Seattle, WA
|
||||
"LAX", // Los Angeles, CA
|
||||
"SJC", // San Jose, CA
|
||||
"PHX" // Phoenix, AZ
|
||||
];
|
||||
|
||||
export default {
|
||||
async fetch(request, env, ctx) {
|
||||
// Create the response headers with CORS support
|
||||
const headers = new Headers({
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
||||
"Access-Control-Allow-Headers": "Content-Type",
|
||||
"Content-Type": "application/json"
|
||||
});
|
||||
|
||||
// Handle OPTIONS requests (pre-flight for CORS)
|
||||
if (request.method === "OPTIONS") {
|
||||
return new Response(null, { headers });
|
||||
}
|
||||
|
||||
// Get the target URL from query params or POST body
|
||||
let targetUrl;
|
||||
if (request.method === "POST") {
|
||||
try {
|
||||
const body = await request.json();
|
||||
targetUrl = body.url;
|
||||
} catch (error) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Invalid JSON body" }),
|
||||
{ headers, status: 400 }
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const url = new URL(request.url);
|
||||
targetUrl = url.searchParams.get("url");
|
||||
}
|
||||
|
||||
// Validate the target URL
|
||||
if (!targetUrl) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Missing 'url' parameter" }),
|
||||
{ headers, status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(targetUrl); // Validate URL format
|
||||
} catch (error) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Invalid URL format" }),
|
||||
{ headers, status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Process all regions in parallel
|
||||
const results = await Promise.allSettled(US_REGIONS.map(async (region) => {
|
||||
return await cacheInRegion(targetUrl, region);
|
||||
}));
|
||||
|
||||
// Compile results
|
||||
const response = {
|
||||
url: targetUrl,
|
||||
cached: true,
|
||||
regionResults: results.map((result, index) => ({
|
||||
region: US_REGIONS[index],
|
||||
success: result.status === "fulfilled",
|
||||
status: result.status === "fulfilled" ? result.value.status : null,
|
||||
error: result.status === "rejected" ? result.reason.message : null
|
||||
}))
|
||||
};
|
||||
|
||||
return new Response(JSON.stringify(response, null, 2), { headers });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to cache the URL in a specific Cloudflare region
|
||||
*
|
||||
* @param {string} url - The URL to cache
|
||||
* @param {string} region - The Cloudflare region code
|
||||
* @returns {Promise<Object>} - The fetch response details
|
||||
*/
|
||||
async function cacheInRegion(url, region) {
|
||||
// Create fetch request with cache control headers
|
||||
const cacheRequest = new Request(url, {
|
||||
headers: {
|
||||
// CF-specific header to route to a specific region
|
||||
"CF-Worker-Request-Region": region,
|
||||
// Headers to encourage caching
|
||||
"Cache-Control": "public, max-age=86400",
|
||||
// Tell Cloudflare that we're a cache warmer
|
||||
"User-Agent": "Cloudflare-Cache-Warmer/1.0"
|
||||
},
|
||||
cf: {
|
||||
// Force caching even if origin has no-store
|
||||
cacheEverything: true,
|
||||
// Cache for 1 day
|
||||
cacheTtl: 86400,
|
||||
// Attempt to resolve through the specified region
|
||||
resolveOverride: region
|
||||
}
|
||||
});
|
||||
|
||||
// Perform the fetch
|
||||
const response = await fetch(cacheRequest);
|
||||
|
||||
return {
|
||||
status: response.status,
|
||||
cached: response.headers.get("CF-Cache-Status") === "HIT" ||
|
||||
response.headers.get("CF-Cache-Status") === "MISS", // MISS on first cache, but still stored
|
||||
headers: {
|
||||
"CF-Cache-Status": response.headers.get("CF-Cache-Status"),
|
||||
"CF-Ray": response.headers.get("CF-Ray")
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user