codetether_agent/provider/
body_cap.rs1use anyhow::{Context, Result, bail};
6use futures::StreamExt;
7use reqwest::Response;
8
9pub const PROVIDER_METADATA_BODY_CAP: usize = 8 * 1024 * 1024; pub async fn read_body_capped(resp: Response, max_bytes: usize) -> Result<Vec<u8>> {
19 if let Some(len) = resp.content_length()
20 && len as usize > max_bytes
21 {
22 bail!(
23 "response body {} B exceeds cap {} B (Content-Length)",
24 len,
25 max_bytes,
26 );
27 }
28 let mut buf: Vec<u8> = Vec::with_capacity(16 * 1024);
29 let mut stream = resp.bytes_stream();
30 while let Some(chunk) = stream.next().await {
31 let chunk = chunk.context("read response chunk")?;
32 if buf.len().saturating_add(chunk.len()) > max_bytes {
33 bail!(
34 "response body exceeded cap {} B after {} B",
35 max_bytes,
36 buf.len(),
37 );
38 }
39 buf.extend_from_slice(&chunk);
40 }
41 Ok(buf)
42}
43
44pub async fn json_capped<T: serde::de::DeserializeOwned>(
47 resp: Response,
48 max_bytes: usize,
49) -> Result<T> {
50 let bytes = read_body_capped(resp, max_bytes).await?;
51 serde_json::from_slice::<T>(&bytes).context("decode capped JSON body")
52}