const PLC_DIRECTORY = "https://plc.directory"; const PATH_RE = /^\/img\/([^/]+)\/plain\/(did:[^/]+)\/([^@/]+)(?:@([^/]+))?$/; export default { async fetch(request, env, ctx) { const url = new URL(request.url); if (url.pathname === "/" || url.pathname === "") { return new Response(LANDING_HTML, { headers: { "Content-Type": "text/html;charset=UTF-8" }, }); } const match = url.pathname.match(PATH_RE); if (!match) return new Response("400: Invalid Path", { status: 400 }); const [_, type, did, cid] = match; const cache = caches.default; const cachedResponse = await cache.match(request); if (cachedResponse) return cachedResponse; const pdsUrl = await resolvePds(did); if (!pdsUrl) { return new Response("404: PDS not found for this DID", { status: 404 }); } try { let blobRes = await fetchBlob(pdsUrl, did, cid); if (blobRes.status === 404 && (type === "avatar" || type === "banner")) { const originalCid = await findOriginalCidFromProfile(pdsUrl, did, type); if (originalCid && originalCid !== cid) { blobRes = await fetchBlob(pdsUrl, did, originalCid); } } if (!blobRes.ok) { return new Response("404: Asset not found on PDS.", { status: 404 }); } const finalRes = new Response(blobRes.body, blobRes); finalRes.headers.set("Cache-Control", "public, s-maxage=604800"); finalRes.headers.set("X-Proxy-Source", "PDS-Direct"); finalRes.headers.set("Content-Disposition", "inline"); ctx.waitUntil(cache.put(request, finalRes.clone())); return finalRes; } catch (err) { return new Response(`502: PDS Error: ${err.message}`, { status: 502 }); } }, }; async function fetchBlob(pdsUrl, did, cid) { return fetch( `${pdsUrl}/xrpc/com.atproto.sync.getBlob?did=${encodeURIComponent(did)}&cid=${encodeURIComponent(cid)}` ); } async function resolvePds(did) { const doc = did.startsWith("did:web:") ? await resolveDidWeb(did) : await resolveDidPlc(did); if (!doc) return null; const pds = doc.service?.find( (s) => s.id === "#atproto_pds" || s.type === "AtprotoPersonalDataServer" ); return pds?.serviceEndpoint ?? null; } async function resolveDidPlc(did) { const res = await fetch(`${PLC_DIRECTORY}/${did}`); if (!res.ok) return null; return res.json(); } async function resolveDidWeb(did) { const identifier = did.slice("did:web:".length); const parts = identifier.split(":"); const host = decodeURIComponent(parts[0]); const didUrl = parts.length === 1 ? `https://${host}/.well-known/did.json` : `https://${host}/${parts.slice(1).map(decodeURIComponent).join("/")}/did.json`; const res = await fetch(didUrl); if (!res.ok) return null; return res.json(); } async function findOriginalCidFromProfile(pdsUrl, did, type) { const res = await fetch( `${pdsUrl}/xrpc/com.atproto.repo.getRecord?repo=${encodeURIComponent(did)}&collection=app.bsky.actor.profile&rkey=self` ); if (!res.ok) return null; const data = await res.json(); return data.value?.[type]?.ref?.$link ?? null; } const LANDING_HTML = `
Paste a cdn.bsky.app image URL to get the cdn.blueat.net equivalent, served directly from the user's PDS and powered by Cloudflare Workers.
This is intended to be used when cdn.bsky.app is down.