actix_web/types/
header.rs

1//! For header extractor helper documentation, see [`Header`](crate::types::Header).
2
3use std::{fmt, ops};
4
5use actix_utils::future::{ready, Ready};
6
7use crate::{
8    dev::Payload, error::ParseError, extract::FromRequest, http::header::Header as ParseHeader,
9    HttpRequest,
10};
11
12/// Extract typed headers from the request.
13///
14/// To extract a header, the inner type `T` must implement the
15/// [`Header`](crate::http::header::Header) trait.
16///
17/// # Examples
18/// ```
19/// use actix_web::{get, web, http::header};
20///
21/// #[get("/")]
22/// async fn index(date: web::Header<header::Date>) -> String {
23///     format!("Request was sent at {}", date.to_string())
24/// }
25/// ```
26#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
27pub struct Header<T>(pub T);
28
29impl<T> Header<T> {
30    /// Unwrap into the inner `T` value.
31    pub fn into_inner(self) -> T {
32        self.0
33    }
34}
35
36impl<T> ops::Deref for Header<T> {
37    type Target = T;
38
39    fn deref(&self) -> &T {
40        &self.0
41    }
42}
43
44impl<T> ops::DerefMut for Header<T> {
45    fn deref_mut(&mut self) -> &mut T {
46        &mut self.0
47    }
48}
49
50impl<T> fmt::Display for Header<T>
51where
52    T: fmt::Display,
53{
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        fmt::Display::fmt(&self.0, f)
56    }
57}
58
59impl<T> FromRequest for Header<T>
60where
61    T: ParseHeader,
62{
63    type Error = ParseError;
64    type Future = Ready<Result<Self, Self::Error>>;
65
66    #[inline]
67    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
68        match ParseHeader::parse(req) {
69            Ok(header) => ready(Ok(Header(header))),
70            Err(err) => ready(Err(err)),
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::{
79        http::{header, Method},
80        test::TestRequest,
81    };
82
83    #[actix_rt::test]
84    async fn test_header_extract() {
85        let (req, mut pl) = TestRequest::default()
86            .insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
87            .insert_header((header::ALLOW, header::Allow(vec![Method::GET])))
88            .to_http_parts();
89
90        let s = Header::<header::ContentType>::from_request(&req, &mut pl)
91            .await
92            .unwrap();
93        assert_eq!(s.into_inner().0, mime::APPLICATION_JSON);
94
95        let s = Header::<header::Allow>::from_request(&req, &mut pl)
96            .await
97            .unwrap();
98        assert_eq!(s.into_inner().0, vec![Method::GET]);
99
100        assert!(Header::<header::Date>::from_request(&req, &mut pl)
101            .await
102            .is_err());
103    }
104}