use anyhow::Result;
use reblessive::tree::Stk;
use crate::api::err::ApiError;
use crate::api::middleware::common::BodyStrategy;
use crate::api::middleware::req::BodyParser;
use crate::api::request::ApiRequest;
use crate::ctx::FrozenContext;
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::expr::{Bytesize, Error};
use crate::fnc::args::{FromPublic, Optional};
use crate::types::PublicValue;
use crate::val::{Closure, Number, Value};
pub async fn body(
(stk, ctx, opt, doc): (&mut Stk, &FrozenContext, &Options, Option<&CursorDoc>),
(FromPublic(mut req), next, Optional(strategy)): (
FromPublic<ApiRequest>,
Box<Closure>,
Optional<FromPublic<BodyStrategy>>,
),
) -> Result<Value> {
let strategy = strategy.map(|x| x.0).unwrap_or_default();
let mut parser =
BodyParser::new(&mut req, strategy, ctx.config.parser.max_object_parsing_depth as usize);
parser.process().await?;
crate::legacy::closure_invoke(&next, stk, ctx, opt, doc, vec![req.into()]).await
}
pub async fn max_body(
(stk, ctx, opt, doc): (&mut Stk, &FrozenContext, &Options, Option<&CursorDoc>),
(FromPublic(req), next, limit): (FromPublic<ApiRequest>, Box<Closure>, Value),
) -> Result<Value> {
let limit = match limit {
Value::Number(Number::Int(i)) if i >= 0 => Bytesize::new(i as u64),
Value::String(ref s) => {
Bytesize::parse(s.as_str()).map_err(|_| Error::InvalidFunctionArguments {
name: "api::req::max_body".to_string(),
message: format!("'{s}' is not a valid byte size (expected e.g. '1mb', '512kb')"),
})?
}
_ => {
anyhow::bail!(Error::InvalidFunctionArguments {
name: "api::req::max_body".to_string(),
message: "Expected a non-negative integer byte count or a byte-size string"
.to_string(),
})
}
};
let size = match req.body {
PublicValue::Bytes(ref b) => Some(b.len() as u64),
PublicValue::String(ref s) => Some(s.len() as u64),
_ => None,
};
if size.is_some_and(|size| size > limit.0) {
return Err(ApiError::RequestBodyTooLarge(limit).into());
}
crate::legacy::closure_invoke(&next, stk, ctx, opt, doc, vec![req.into()]).await
}