Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
wisp.place
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(¤t_data)
46 .into_diagnostic()?;
47 }
48
49 // Then, decompress gzip if needed
50 if is_gzipped {
51 let mut decoder = GzDecoder::new(¤t_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