use anyhow::{Context, Result, bail};
use futures::StreamExt;
use reqwest::Response;
pub const PROVIDER_METADATA_BODY_CAP: usize = 8 * 1024 * 1024;
pub async fn read_body_capped(resp: Response, max_bytes: usize) -> Result<Vec<u8>> {
if let Some(len) = resp.content_length()
&& len as usize > max_bytes
{
bail!(
"response body {} B exceeds cap {} B (Content-Length)",
len,
max_bytes,
);
}
let mut buf: Vec<u8> = Vec::with_capacity(16 * 1024);
let mut stream = resp.bytes_stream();
while let Some(chunk) = stream.next().await {
let chunk = chunk.context("read response chunk")?;
if buf.len().saturating_add(chunk.len()) > max_bytes {
bail!(
"response body exceeded cap {} B after {} B",
max_bytes,
buf.len(),
);
}
buf.extend_from_slice(&chunk);
}
Ok(buf)
}
pub async fn json_capped<T: serde::de::DeserializeOwned>(
resp: Response,
max_bytes: usize,
) -> Result<T> {
let bytes = read_body_capped(resp, max_bytes).await?;
serde_json::from_slice::<T>(&bytes).context("decode capped JSON body")
}