protocol/header/
blob_meta.rs

1use headers::{Error, Header, HeaderName, HeaderValue};
2
3use interface::BlobMetaRequest;
4
5use once_cell::sync::Lazy;
6
7static X_BLOB_META: Lazy<HeaderName> = Lazy::new(|| HeaderName::from_static("x-blob-meta"));
8
9pub struct BlobMetaHeader(pub BlobMetaRequest);
10
11// God bless typed headers 😍
12impl Header for BlobMetaHeader {
13    fn name() -> &'static HeaderName {
14        &X_BLOB_META
15    }
16
17    fn decode<'i, I>(values: &mut I) -> std::result::Result<Self, Error>
18    where
19        Self: Sized,
20        I: Iterator<Item = &'i HeaderValue>,
21    {
22        let first_value = values.next().ok_or_else(Error::invalid)?;
23        let json_bytes = base64::decode(first_value.as_bytes()).map_err(|e| {
24            tracing::debug!("failed to b64 decode blob meta: {e}");
25            Error::invalid()
26        })?;
27        let meta: BlobMetaRequest = serde_json::from_slice(&json_bytes).map_err(|e| {
28            tracing::debug!("failed to deserialize blob meta: {e}");
29            Error::invalid()
30        })?;
31
32        if values.next().is_some() {
33            tracing::debug!("x-blob-meta doesn't support multiple assignment");
34            return Err(Error::invalid());
35        }
36
37        Ok(Self(meta))
38    }
39
40    fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
41        let serialized = serde_json::to_vec(&self.0).unwrap(); // BlobMetaRequest is always serializable.
42        let encoded = base64::encode(&serialized);
43        let value = HeaderValue::from_str(&encoded).unwrap(); // b64 is always a valid header value.
44
45        // TODO: Replace the vec allocation with Extend::extend_one once it is stabilized
46        values.extend(vec![value].into_iter())
47    }
48}