Skip to main content

silent/extractor/
from_request.rs

1use async_trait::async_trait;
2
3use crate::core::path_param::PathParam as CorePathParam;
4use crate::{Request, Response, SilentError, headers::HeaderMapExt};
5
6#[allow(deprecated)]
7use super::types::Configs;
8use super::types::{
9    Extension, Form, Json, Method, Path, Query, RemoteAddr, State, TypedHeader, Uri, Version,
10};
11
12/// `FromRequest` 是萃取器的核心 trait,用于从 HTTP 请求中提取特定类型的数据。
13///
14/// 通过实现这个 trait,您可以创建自定义的萃取器,从请求中提取任何需要的数据。
15/// 所有内置萃取器(Path、Query、Json 等)都实现了这个 trait。
16///
17/// ## 基本用法
18///
19/// 要实现一个自定义萃取器,您需要:
20/// 1. 定义您的数据类型
21/// 2. 实现 `FromRequest` trait
22/// 3. 在处理函数中使用萃取器
23///
24/// ## 示例:创建 JWT 令牌萃取器
25///
26/// ```rust
27/// use async_trait::async_trait;
28/// use silent::extractor::FromRequest;
29/// use silent::{Request, Result, SilentError};
30///
31/// struct JwtToken(String);
32///
33/// #[async_trait]
34/// impl FromRequest for JwtToken {
35///     type Rejection = SilentError;
36///
37///     async fn from_request(req: &mut Request) -> std::result::Result<Self, Self::Rejection> {
38///         let token = req.headers()
39///             .get("authorization")
40///             .and_then(|v| v.to_str().ok())
41///             .and_then(|s| s.strip_prefix("Bearer "))
42///             .map(|s| s.to_string())
43///             .ok_or(SilentError::ParamsNotFound)?;
44///
45///         Ok(JwtToken(token))
46///     }
47/// }
48///
49/// // 使用自定义萃取器
50/// async fn protected_handler(token: JwtToken) -> Result<String> {
51///     Ok(format!("访问受保护的资源,Token: {}", token.0))
52/// }
53/// ```
54///
55/// ## 错误处理
56///
57/// `FromRequest` 的 `Rejection` 类型决定了萃取失败时的错误类型。常用的错误类型:
58/// - `SilentError`:框架内置错误,包含 `ParamsNotFound`、`ParamsEmpty` 等
59/// - `Response`:直接返回 HTTP 响应
60///
61/// ## 组合使用
62///
63/// 多个萃取器可以组合使用:
64///
65/// ```rust
66/// use silent::Result;
67/// use silent::extractor::{Path, Query, Json};
68/// use serde::Deserialize;
69///
70/// #[derive(Deserialize)]
71/// struct Page {
72///     page: u32,
73///     size: u32,
74/// }
75///
76/// #[derive(Deserialize)]
77/// struct Data {
78///     name: String,
79/// }
80///
81/// async fn handler(
82///     (Path(id), Query(p), Json(data)): (Path<i64>, Query<Page>, Json<Data>),
83/// ) -> Result<String> {
84///     // 处理提取的数据
85///     Ok("成功".to_string())
86/// }
87/// ```
88///
89/// ## 可选参数
90///
91/// 使用 `Option<T>` 可以处理可选参数:
92///
93/// ```rust
94/// use silent::Result;
95/// use silent::extractor::Path;
96///
97/// async fn handler(opt_id: Option<Path<i64>>) -> Result<String> {
98///     match opt_id {
99///         Some(Path(id)) => Ok(format!("ID: {}", id)),
100///         None => Ok("无ID".to_string()),
101///     }
102/// }
103/// ```
104#[async_trait]
105pub trait FromRequest: Sized {
106    /// 萃取失败时的错误类型
107    ///
108    /// 这个类型必须能够转换为 HTTP 响应(实现了 `Into<Response>`)
109    type Rejection: Into<crate::Response> + Send + 'static;
110
111    /// 从请求中提取数据
112    ///
113    /// # 参数
114    ///
115    /// * `req` - 可变的请求引用,可以从中提取数据
116    ///
117    /// # 返回值
118    ///
119    /// 返回 `Result<Self, Self::Rejection>`:
120    /// - 成功时返回 `Ok(extracted_value)`
121    /// - 失败时返回 `Err(error)`
122    ///
123    /// # 示例
124    ///
125    /// 参见上面 `FromRequest` trait 的完整示例。
126    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection>;
127}
128
129#[async_trait]
130impl<T> FromRequest for Path<T>
131where
132    for<'de> T: serde::Deserialize<'de> + Send + 'static,
133{
134    type Rejection = SilentError;
135
136    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
137        use crate::core::serde::{from_str_map, from_str_val};
138        let params = req.path_params();
139        if params.is_empty() {
140            return Err(SilentError::ParamsEmpty);
141        }
142
143        if params.len() == 1 {
144            let value = params.values().next().unwrap();
145            let single = path_param_to_string(value);
146            let parsed: T = from_str_val(single.as_str())?;
147            return Ok(Path(parsed));
148        }
149
150        let map_iter = params
151            .iter()
152            .map(|(k, v)| (k.as_str(), path_param_to_string(v)));
153        let parsed: T = from_str_map(map_iter)?;
154        Ok(Path(parsed))
155    }
156}
157
158#[async_trait]
159impl<T> FromRequest for Query<T>
160where
161    for<'de> T: serde::Deserialize<'de> + Send + 'static,
162{
163    type Rejection = SilentError;
164
165    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
166        let value = req.params_parse::<T>()?;
167        Ok(Query(value))
168    }
169}
170
171#[async_trait]
172impl<T> FromRequest for Json<T>
173where
174    for<'de> T: serde::Deserialize<'de> + Send + 'static,
175{
176    type Rejection = SilentError;
177
178    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
179        let value = req.json_parse::<T>().await?;
180        Ok(Json(value))
181    }
182}
183
184#[async_trait]
185impl<T> FromRequest for Form<T>
186where
187    for<'de> T: serde::Deserialize<'de> + serde::Serialize + Send + 'static,
188{
189    type Rejection = SilentError;
190
191    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
192        let value = req.form_parse::<T>().await?;
193        Ok(Form(value))
194    }
195}
196
197#[async_trait]
198impl<T> FromRequest for State<T>
199where
200    T: Send + Sync + Clone + 'static,
201{
202    type Rejection = SilentError;
203
204    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
205        let val = req.get_state::<T>()?.clone();
206        Ok(State(val))
207    }
208}
209
210#[allow(deprecated)]
211#[async_trait]
212impl<T> FromRequest for Configs<T>
213where
214    T: Send + Sync + Clone + 'static,
215{
216    type Rejection = SilentError;
217
218    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
219        let cfg = req.get_state::<T>()?.clone();
220        Ok(Configs(cfg))
221    }
222}
223
224#[async_trait]
225impl<T> FromRequest for Extension<T>
226where
227    T: Clone + Send + Sync + 'static,
228{
229    type Rejection = SilentError;
230
231    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
232        let ext = req
233            .extensions()
234            .get::<T>()
235            .cloned()
236            .ok_or(SilentError::ParamsNotFound)?;
237        Ok(Extension(ext))
238    }
239}
240
241#[async_trait]
242impl<H> FromRequest for TypedHeader<H>
243where
244    H: headers::Header + Send + 'static,
245{
246    type Rejection = SilentError;
247
248    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
249        let h = req
250            .headers()
251            .typed_get::<H>()
252            .ok_or(SilentError::ParamsNotFound)?;
253        Ok(TypedHeader(h))
254    }
255}
256
257#[async_trait]
258impl FromRequest for Method {
259    type Rejection = SilentError;
260    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
261        Ok(Method(req.method().clone()))
262    }
263}
264
265#[async_trait]
266impl FromRequest for Uri {
267    type Rejection = SilentError;
268    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
269        Ok(Uri(req.uri().clone()))
270    }
271}
272
273#[async_trait]
274impl FromRequest for Version {
275    type Rejection = SilentError;
276    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
277        Ok(Version(req.version()))
278    }
279}
280
281#[async_trait]
282impl FromRequest for RemoteAddr {
283    type Rejection = SilentError;
284    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
285        Ok(RemoteAddr(req.remote()))
286    }
287}
288
289#[async_trait]
290impl<A> FromRequest for (A,)
291where
292    A: FromRequest + Send + 'static,
293{
294    type Rejection = Response;
295
296    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
297        let a = match <A as FromRequest>::from_request(req).await {
298            Ok(v) => v,
299            Err(e) => return Err(e.into()),
300        };
301        Ok((a,))
302    }
303}
304
305#[async_trait]
306impl<A, B> FromRequest for (A, B)
307where
308    A: FromRequest + Send + 'static,
309    B: FromRequest + Send + 'static,
310{
311    type Rejection = Response;
312
313    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
314        let a = match <A as FromRequest>::from_request(req).await {
315            Ok(v) => v,
316            Err(e) => return Err(e.into()),
317        };
318        let b = match <B as FromRequest>::from_request(req).await {
319            Ok(v) => v,
320            Err(e) => return Err(e.into()),
321        };
322        Ok((a, b))
323    }
324}
325
326#[async_trait]
327impl<A, B, C> FromRequest for (A, B, C)
328where
329    A: FromRequest + Send + 'static,
330    B: FromRequest + Send + 'static,
331    C: FromRequest + Send + 'static,
332{
333    type Rejection = Response;
334
335    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
336        let a = match <A as FromRequest>::from_request(req).await {
337            Ok(v) => v,
338            Err(e) => return Err(e.into()),
339        };
340        let b = match <B as FromRequest>::from_request(req).await {
341            Ok(v) => v,
342            Err(e) => return Err(e.into()),
343        };
344        let c = match <C as FromRequest>::from_request(req).await {
345            Ok(v) => v,
346            Err(e) => return Err(e.into()),
347        };
348        Ok((a, b, c))
349    }
350}
351
352#[async_trait]
353impl<A, B, C, D> FromRequest for (A, B, C, D)
354where
355    A: FromRequest + Send + 'static,
356    B: FromRequest + Send + 'static,
357    C: FromRequest + Send + 'static,
358    D: FromRequest + Send + 'static,
359{
360    type Rejection = Response;
361
362    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
363        let a = match <A as FromRequest>::from_request(req).await {
364            Ok(v) => v,
365            Err(e) => return Err(e.into()),
366        };
367        let b = match <B as FromRequest>::from_request(req).await {
368            Ok(v) => v,
369            Err(e) => return Err(e.into()),
370        };
371        let c = match <C as FromRequest>::from_request(req).await {
372            Ok(v) => v,
373            Err(e) => return Err(e.into()),
374        };
375        let d = match <D as FromRequest>::from_request(req).await {
376            Ok(v) => v,
377            Err(e) => return Err(e.into()),
378        };
379        Ok((a, b, c, d))
380    }
381}
382
383#[async_trait]
384impl<T> FromRequest for Option<T>
385where
386    T: FromRequest + Send + 'static,
387{
388    type Rejection = Response;
389
390    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
391        match T::from_request(req).await {
392            Ok(v) => Ok(Some(v)),
393            Err(_e) => Ok(None),
394        }
395    }
396}
397
398#[async_trait]
399impl<T> FromRequest for Result<T, Response>
400where
401    T: FromRequest + Send + 'static,
402{
403    type Rejection = Response;
404
405    async fn from_request(req: &mut Request) -> Result<Self, Self::Rejection> {
406        match T::from_request(req).await {
407            Ok(v) => Ok(Ok(v)),
408            Err(e) => Ok(Err(e.into())),
409        }
410    }
411}
412
413#[inline]
414fn path_param_to_string(param: &CorePathParam) -> String {
415    match param {
416        CorePathParam::Str(s) | CorePathParam::Path(s) => s.as_str().to_string(),
417        CorePathParam::Int(v) => v.to_string(),
418        CorePathParam::Int32(v) => v.to_string(),
419        CorePathParam::Int64(v) => v.to_string(),
420        CorePathParam::UInt32(v) => v.to_string(),
421        CorePathParam::UInt64(v) => v.to_string(),
422        CorePathParam::Uuid(u) => u.to_string(),
423    }
424}