use super::body::{parse_form, parse_json};
use super::extract::FromRequest;
use super::Request;
use crate::error::{FrameworkError, ValidationErrors};
use async_trait::async_trait;
use serde::de::DeserializeOwned;
use validator::Validate;
#[async_trait]
pub trait FormRequest: Sized + DeserializeOwned + Validate + Send {
fn authorize(_req: &Request) -> bool {
true
}
async fn extract(req: Request) -> Result<Self, FrameworkError> {
if !Self::authorize(&req) {
return Err(FrameworkError::Unauthorized);
}
let content_type = req.content_type().map(|s| s.to_string());
let (_, bytes) = req.body_bytes().await?;
let data: Self = match content_type.as_deref() {
Some(ct) if ct.starts_with("application/x-www-form-urlencoded") => parse_form(&bytes)?,
_ => parse_json(&bytes)?,
};
if let Err(errors) = data.validate() {
return Err(FrameworkError::Validation(
ValidationErrors::from_validator(errors),
));
}
Ok(data)
}
}
#[async_trait]
impl<T: FormRequest> FromRequest for T {
async fn from_request(req: Request) -> Result<Self, FrameworkError> {
T::extract(req).await
}
}