1use hyper::body::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 json_body<T: DeserializeOwned>(req: Request<Incoming>) -> Result<T, ServeError> {
23 let (parts, body) = req.into_parts();
24 let max = parts
25 .extensions
26 .get::<MaxBodySize>()
27 .map(|m| m.0)
28 .unwrap_or(DEFAULT_MAX_BODY_SIZE);
29
30 if let Some(content_length) = parts.headers.get("content-length") {
31 if let Ok(s) = content_length.to_str() {
32 if let Ok(len) = s.parse::<usize>() {
33 if len > max {
34 return Err(ServeError::new(413, "request body too large"));
35 }
36 }
37 }
38 }
39
40 let limited = Limited::new(body, max);
41 let collected = limited
42 .collect()
43 .await
44 .map_err(|e| {
45 if e.downcast_ref::<LengthLimitError>().is_some() {
46 ServeError::new(413, "request body too large")
47 } else {
48 ServeError::new(400, "failed to read request body")
49 }
50 })?;
51 let bytes = collected.to_bytes();
52 serde_json::from_slice(&bytes)
53 .map_err(|_| ServeError::new(400, "invalid json body"))
54}