a tool for shared writing and social publishing
at feature/backdate 58 lines 1.6 kB view raw
1import { IdResolver } from "@atproto/identity"; 2import { NextRequest, NextResponse } from "next/server"; 3 4let idResolver = new IdResolver(); 5 6/** 7 * Fetches a blob from an AT Protocol PDS given a DID and CID 8 * Returns the Response object or null if the blob couldn't be fetched 9 */ 10export async function fetchAtprotoBlob( 11 did: string, 12 cid: string, 13): Promise<Response | null> { 14 if (!did || !cid) return null; 15 16 let identity = await idResolver.did.resolve(did); 17 let service = identity?.service?.find((f) => f.id === "#atproto_pds"); 18 if (!service) return null; 19 20 const response = await fetch( 21 `${service.serviceEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`, 22 { 23 headers: { 24 "Accept-Encoding": "gzip, deflate, br, zstd", 25 }, 26 }, 27 ); 28 29 if (!response.ok) return null; 30 31 return response; 32} 33 34export async function GET(req: NextRequest) { 35 const url = new URL(req.url); 36 const params = { 37 did: url.searchParams.get("did") ?? "", 38 cid: url.searchParams.get("cid") ?? "", 39 }; 40 41 const response = await fetchAtprotoBlob(params.did, params.cid); 42 if (!response) return new NextResponse(null, { status: 404 }); 43 44 // Clone the response to modify headers 45 const cachedResponse = new Response(response.body, response); 46 47 // Set cache-control header to cache indefinitely 48 cachedResponse.headers.set( 49 "Cache-Control", 50 "public, max-age=31536000, immutable, s-maxage=86400, stale-while-revalidate=604800", 51 ); 52 cachedResponse.headers.set( 53 "CDN-Cache-Control", 54 "s-maxage=86400, stale-while-revalidate=86400", 55 ); 56 57 return cachedResponse; 58}