Skip to main content

bee/file/
chunk.rs

1//! `/chunks` endpoints: upload / download a single content-addressed
2//! chunk.
3
4use bytes::Bytes;
5use reqwest::Method;
6use serde::Deserialize;
7
8use crate::api::{
9    DownloadOptions, UploadOptions, UploadResult, prepare_download_headers, prepare_upload_headers,
10};
11use crate::client::{Inner, MAX_JSON_RESPONSE_BYTES, request};
12use crate::swarm::{BatchId, Error, Reference};
13
14use super::FileApi;
15
16#[derive(Deserialize)]
17struct UploadBody {
18    reference: String,
19}
20
21impl FileApi {
22    /// Upload a single raw chunk (`span || payload`) via
23    /// `POST /chunks`.
24    pub async fn upload_chunk(
25        &self,
26        batch_id: &BatchId,
27        data: impl Into<Bytes>,
28        opts: Option<&UploadOptions>,
29    ) -> Result<UploadResult, Error> {
30        let builder = request(&self.inner, Method::POST, "chunks")?
31            .header("Content-Type", "application/octet-stream")
32            .body(data.into());
33        let builder = Inner::apply_headers(builder, prepare_upload_headers(batch_id, opts));
34        let resp = self.inner.send(builder).await?;
35        let headers = resp.headers().clone();
36        let body: UploadBody = serde_json::from_slice(&Inner::read_capped(resp, MAX_JSON_RESPONSE_BYTES).await?)?;
37        UploadResult::from_response(&body.reference, &headers)
38    }
39
40    /// Download a single chunk's bytes via `GET /chunks/{ref}`.
41    pub async fn download_chunk(
42        &self,
43        reference: &Reference,
44        opts: Option<&DownloadOptions>,
45    ) -> Result<Bytes, Error> {
46        let resp = download_chunk_response(&self.inner, reference, opts).await?;
47        Ok(resp.bytes().await?)
48    }
49}
50
51/// Internal helper: return the raw `Response` so other modules
52/// (feeds, GSOC subscribe verification) can inspect headers without a
53/// double round-trip.
54pub(crate) async fn download_chunk_response(
55    inner: &Inner,
56    reference: &Reference,
57    opts: Option<&DownloadOptions>,
58) -> Result<reqwest::Response, Error> {
59    let path = format!("chunks/{}", reference.to_hex());
60    let builder = request(inner, Method::GET, &path)?;
61    let builder = Inner::apply_headers(builder, prepare_download_headers(opts));
62    inner.send(builder).await
63}