Skip to main content

actix_web/types/
header.rs

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