Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place
at main 2.1 kB view raw
1use base64::Engine; 2use bytes::Bytes; 3use flate2::read::GzDecoder; 4use jacquard_common::types::blob::BlobRef; 5use miette::IntoDiagnostic; 6use std::io::Read; 7use url::Url; 8 9/// Download a blob from the PDS 10pub async fn download_blob(pds_url: &Url, blob_ref: &BlobRef<'_>, did: &str) -> miette::Result<Bytes> { 11 // Extract CID from blob ref 12 let cid = blob_ref.blob().r#ref.to_string(); 13 14 // Construct blob download URL 15 // The correct endpoint is: /xrpc/com.atproto.sync.getBlob?did={did}&cid={cid} 16 let blob_url = pds_url 17 .join(&format!("/xrpc/com.atproto.sync.getBlob?did={}&cid={}", did, cid)) 18 .into_diagnostic()?; 19 20 let client = reqwest::Client::new(); 21 let response = client 22 .get(blob_url) 23 .send() 24 .await 25 .into_diagnostic()?; 26 27 if !response.status().is_success() { 28 return Err(miette::miette!( 29 "Failed to download blob: {}", 30 response.status() 31 )); 32 } 33 34 let bytes = response.bytes().await.into_diagnostic()?; 35 Ok(bytes) 36} 37 38/// Decompress and decode a blob (base64 + gzip) 39pub fn decompress_blob(data: &[u8], is_base64: bool, is_gzipped: bool) -> miette::Result<Vec<u8>> { 40 let mut current_data = data.to_vec(); 41 42 // First, decode base64 if needed 43 if is_base64 { 44 current_data = base64::prelude::BASE64_STANDARD 45 .decode(&current_data) 46 .into_diagnostic()?; 47 } 48 49 // Then, decompress gzip if needed 50 if is_gzipped { 51 let mut decoder = GzDecoder::new(&current_data[..]); 52 let mut decompressed = Vec::new(); 53 decoder.read_to_end(&mut decompressed).into_diagnostic()?; 54 current_data = decompressed; 55 } 56 57 Ok(current_data) 58} 59 60/// Download and decompress a blob 61pub async fn download_and_decompress_blob( 62 pds_url: &Url, 63 blob_ref: &BlobRef<'_>, 64 did: &str, 65 is_base64: bool, 66 is_gzipped: bool, 67) -> miette::Result<Vec<u8>> { 68 let data = download_blob(pds_url, blob_ref, did).await?; 69 decompress_blob(&data, is_base64, is_gzipped) 70} 71