1use hyper::body::{Bytes, Incoming};
2use hyper::Request;
3use http_body_util::{BodyExt, LengthLimitError, Limited};
4use serde::de::DeserializeOwned;
5
6use crate::error::ServeError;
7
8pub const DEFAULT_MAX_BODY_SIZE: usize = 2_097_152;
10
11#[derive(Clone, Copy, Debug)]
16pub struct MaxBodySize(pub usize);
17
18pub async fn body_bytes(req: Request<Incoming>) -> Result<Bytes, ServeError> {
30 let (parts, body) = req.into_parts();
31 let max = parts
32 .extensions
33 .get::<MaxBodySize>()
34 .map(|m| m.0)
35 .unwrap_or(DEFAULT_MAX_BODY_SIZE);
36
37 if let Some(content_length) = parts.headers.get("content-length") {
38 if let Ok(s) = content_length.to_str() {
39 if let Ok(len) = s.parse::<usize>() {
40 if len > max {
41 return Err(ServeError::new(413, "request body too large"));
42 }
43 }
44 }
45 }
46
47 let limited = Limited::new(body, max);
48 let collected = limited
49 .collect()
50 .await
51 .map_err(|e| {
52 if e.downcast_ref::<LengthLimitError>().is_some() {
53 ServeError::new(413, "request body too large")
54 } else {
55 ServeError::new(400, "failed to read request body")
56 }
57 })?;
58 Ok(collected.to_bytes())
59}
60
61pub async fn json_body<T: DeserializeOwned>(req: Request<Incoming>) -> Result<T, ServeError> {
66 let bytes = body_bytes(req).await?;
67 serde_json::from_slice(&bytes).map_err(|_| ServeError::new(400, "invalid json body"))
68}