the worker settings on cloudfare have a route set to christopherpaine.org/private_assets
routes define which HTTP requests should be handled by specific worker script.
clicking a link typically invokes a GET method .
const ALLOWED_ORIGINS = [
"https://christopherpaine.org",
"http://localhost:4000"
];
defines a constant array called ALLOWED_ORIGINS. it lists the origins (protocol + domain + optional port) that are allowed to access.
it is usually used for CORS (Cross-Origin Resource Sharing) to control which websites can make requests to server.
requests from any origin not in this list would be blocked.
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request));
});
this is for the cloudfare worker and listens for incoming http requests (fetch events) everytime a request hits the worker the arrow function => is run.
instead of the default behaviour respond with whatever handleRequest returns.
handleRequest is a function defined elsewhere that takes the request and returns a response
in short the event listener intercepts network requests and allows for a custom response programmatically.
async function handleRequest(request) {
means the function is asynchronous and will always return a Promise , even when you dont explicitly return one.
const origin = request.headers.get("Origin") || "";
const referer = request.headers.get("Referer") || "";
this part retrieves values from an incoming request object.
the first obtains origin (scheme + domain + port ) of the request. the second obtains the referer - which is the url of the page that made the request.
for example
origin could be https://example.com
and
referrer could be https://example.com/page?query=123
// ---- CORS headers ----
const corsHeaders = new Headers();
corsHeaders.set("Access-Control-Allow-Origin", origin || "*");
corsHeaders.set("Vary", "Origin");
corsHeaders.set("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
corsHeaders.set("Access-Control-Allow-Headers", "Authorization, Content-Type");
corsHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
sets up a CORS policy. the purpose of a CORS (Cross-Origin Resource Sharing) policy is to control and secure how web browsers allow web pages from one origin to access resources on another origin.
(which to be fair is what i am probably doing with christopherpaine.org accessign resources from backblaze.
// Handle preflight requests
if (request.method === "OPTIONS") {
return new Response(null, { status: 204, headers: corsHeaders });
}
browsers send an OPTIONS request before certain cross-origin requests to check what methods and headers the server allows. this is called a pre-flight request
: : : : : : : : : :
this is a part of code that i have been advised to fix
// ---- Forward file + headers ----
const headers = new Headers(fileResponse.headers);
to
const range = request.headers.get("Range");
const fileResponse = await fetch(downloadUrl, {
headers: {
"Authorization": authData.authorizationToken,
...(range ? { "Range": range } : {})
}
});
to enable partial content fetching if the incoming request has one
also advised to fix the folowing bit at the end:
return new Response(fileResponse.body, { headers });
to
return new Response(fileResponse.body, {
status: fileResponse.status,
statusText: fileResponse.statusText,
headers
});
const ALLOWED_ORIGINS = [
"https://christopherpaine.org",
"http://localhost:4000"
];
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const origin = request.headers.get("Origin") || "";
const referer = request.headers.get("Referer") || "";
// ---- CORS headers ----
const corsHeaders = new Headers();
corsHeaders.set("Access-Control-Allow-Origin", origin || "*");
corsHeaders.set("Vary", "Origin");
corsHeaders.set("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
corsHeaders.set("Access-Control-Allow-Headers", "Authorization, Content-Type");
corsHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
// Handle preflight requests
if (request.method === "OPTIONS") {
return new Response(null, { status: 204, headers: corsHeaders });
}
// ---- Resolve asset path ----
const url = new URL(request.url);
const assetPath = url.pathname.replace("/private_assets/", "");
// ---- Origin / Referer gate ----
// PDFs bypass origin/referer check to allow iframe embedding
if (!assetPath.endsWith(".pdf")) {
if (!ALLOWED_ORIGINS.some(o => origin.startsWith(o) || referer.startsWith(o))) {
return new Response("Forbidden", { status: 403, headers: corsHeaders });
}
}
// ---- Authorize with Backblaze B2 ----
const authResponse = await fetch(
"https://api.backblazeb2.com/b2api/v2/b2_authorize_account",
{
headers: {
"Authorization": "Basic " + btoa("003f18b31f77ee90000000004:K003m+xPsN4IVu2o0WCqHXe+wgujA48")
}
}
);
const authData = await authResponse.json();
const downloadUrl = `${authData.downloadUrl}/file/cp-private-assets/${assetPath}`;
// ---- Fetch file ----
const fileResponse = await fetch(downloadUrl, {
headers: { "Authorization": authData.authorizationToken }
});
if (!fileResponse.ok) {
const text = await fileResponse.text();
return new Response(
`B2 error ${fileResponse.status}:\n${text}`,
{ status: 500, headers: { "Content-Type": "text/plain", ...Object.fromEntries(corsHeaders) } }
);
}
// ---- Forward file + headers ----
const headers = new Headers(fileResponse.headers);
// Set caching
headers.set("Cache-Control", "public, max-age=31536000");
// Merge CORS
for (const [k, v] of corsHeaders) {
headers.set(k, v);
}
// ✅ PDF fix for iframes
if (assetPath.endsWith(".pdf")) {
headers.set("Content-Type", "application/pdf");
headers.set("Content-Disposition", "inline");
headers.delete("X-Frame-Options");
headers.delete("Content-Security-Policy");
}
return new Response(fileResponse.body, { headers });
}