boluo/extract/
header.rs

1use std::ops::{Deref, DerefMut};
2
3use boluo_core::extract::{FromRequest, OptionalFromRequest};
4use boluo_core::http::HeaderName;
5use boluo_core::request::Request;
6use headers::{Header, HeaderMapExt};
7
8/// 获取请求标头值的提取器。
9///
10/// `T` 需要实现 [`Header`]。
11///
12/// # 例子
13///
14/// ```
15/// use boluo::extract::TypedHeader;
16/// use boluo::headers::Host;
17///
18/// #[boluo::route("/", method = "GET")]
19/// async fn handler(TypedHeader(host): TypedHeader<Host>) {
20///     // ...
21/// }
22/// ```
23#[derive(Debug, Clone, Copy)]
24pub struct TypedHeader<T>(pub T);
25
26impl<T> Deref for TypedHeader<T> {
27    type Target = T;
28
29    #[inline]
30    fn deref(&self) -> &Self::Target {
31        &self.0
32    }
33}
34
35impl<T> DerefMut for TypedHeader<T> {
36    #[inline]
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.0
39    }
40}
41
42impl<T> TypedHeader<T> {
43    /// 得到内部的值。
44    #[inline]
45    pub fn into_inner(this: Self) -> T {
46        this.0
47    }
48}
49
50impl<T> FromRequest for TypedHeader<T>
51where
52    T: Header,
53{
54    type Error = TypedHeaderExtractError;
55
56    async fn from_request(req: &mut Request) -> Result<Self, Self::Error> {
57        Option::<TypedHeader<T>>::from_request(req)
58            .await?
59            .ok_or_else(|| TypedHeaderExtractError::MissingHeader { name: T::name() })
60    }
61}
62
63impl<T> OptionalFromRequest for TypedHeader<T>
64where
65    T: Header,
66{
67    type Error = TypedHeaderExtractError;
68
69    async fn from_request(req: &mut Request) -> Result<Option<Self>, Self::Error> {
70        req.headers()
71            .typed_try_get()
72            .map(|v| v.map(TypedHeader))
73            .map_err(|source| TypedHeaderExtractError::ParseError {
74                name: T::name(),
75                source,
76            })
77    }
78}
79
80/// 获取请求标头值错误。
81#[derive(Debug)]
82pub enum TypedHeaderExtractError {
83    /// 标头不存在。
84    MissingHeader {
85        /// 标头名。
86        name: &'static HeaderName,
87    },
88    /// 解析错误。
89    ParseError {
90        /// 标头名。
91        name: &'static HeaderName,
92        /// 错误源。
93        source: headers::Error,
94    },
95}
96
97impl std::fmt::Display for TypedHeaderExtractError {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        match self {
100            TypedHeaderExtractError::MissingHeader { name } => {
101                write!(f, "missing request header `{name}`")
102            }
103            TypedHeaderExtractError::ParseError { name, source } => {
104                write!(f, "failed to parse request header `{name}` ({source})")
105            }
106        }
107    }
108}
109
110impl std::error::Error for TypedHeaderExtractError {}