nestforge_core/
request.rs1use std::ops::Deref;
2
3use axum::{
4 extract::{FromRequest, FromRequestParts, Path},
5 http::request::Parts,
6};
7use serde::de::DeserializeOwned;
8
9use crate::HttpException;
10
11pub struct Param<T>(pub T);
21
22impl<T> Deref for Param<T> {
23 type Target = T;
24
25 fn deref(&self) -> &Self::Target {
26 &self.0
27 }
28}
29
30impl<S, T> FromRequestParts<S> for Param<T>
34where
35 S: Send + Sync,
36 T: DeserializeOwned + Send + 'static,
37{
38 type Rejection = HttpException;
39
40 async fn from_request_parts(
41 parts: &mut Parts,
42 state: &S,
43 ) -> Result<Self, Self::Rejection> {
44 let Path(value) = Path::<T>::from_request_parts(parts, state)
45 .await
46 .map_err(|_| HttpException::bad_request("Invalid route parameter"))?;
47
48 Ok(Self(value))
49 }
50}
51
52pub struct Body<T>(pub T);
62
63impl<T> Deref for Body<T> {
64 type Target = T;
65
66 fn deref(&self) -> &Self::Target {
67 &self.0
68 }
69}
70
71impl<T> Body<T> {
72 pub fn into_inner(self) -> T {
73 self.0
74 }
75}
76
77impl<S, T> FromRequest<S> for Body<T>
81where
82 S: Send + Sync,
83 T: DeserializeOwned + Send + 'static,
84{
85 type Rejection = HttpException;
86
87 async fn from_request(
88 req: axum::extract::Request,
89 state: &S,
90 ) -> Result<Self, Self::Rejection> {
91 let axum::Json(value) = axum::Json::<T>::from_request(req, state)
92 .await
93 .map_err(|_| HttpException::bad_request("Invalid JSON body"))?;
94
95 Ok(Self(value))
96 }
97}