rama_http_headers/common/
access_control_allow_headers.rs

1use std::iter::FromIterator;
2
3use rama_http_types::{HeaderName, HeaderValue};
4
5use crate::util::FlatCsv;
6
7/// `Access-Control-Allow-Headers` header, part of
8/// [CORS](http://www.w3.org/TR/cors/#access-control-allow-headers-response-header)
9///
10/// The `Access-Control-Allow-Headers` header indicates, as part of the
11/// response to a preflight request, which header field names can be used
12/// during the actual request.
13///
14/// # ABNF
15///
16/// ```text
17/// Access-Control-Allow-Headers: "Access-Control-Allow-Headers" ":" #field-name
18/// ```
19///
20/// # Example values
21/// * `accept-language, date`
22///
23/// # Examples
24///
25/// ```
26/// use rama_http_types::header::{CACHE_CONTROL, CONTENT_TYPE};
27/// use rama_http_headers::AccessControlAllowHeaders;
28///
29/// let allow_headers = vec![CACHE_CONTROL, CONTENT_TYPE]
30///     .into_iter()
31///     .collect::<AccessControlAllowHeaders>();
32/// ```
33#[derive(Clone, Debug, PartialEq)]
34pub struct AccessControlAllowHeaders(FlatCsv);
35
36derive_header! {
37    AccessControlAllowHeaders(_),
38    name: ACCESS_CONTROL_ALLOW_HEADERS
39}
40
41impl AccessControlAllowHeaders {
42    /// Returns an iterator over `HeaderName`s contained within.
43    pub fn iter(&self) -> impl Iterator<Item = HeaderName> + '_ {
44        self.0
45            .iter()
46            .map(|s| s.parse().ok())
47            .take_while(|val| val.is_some())
48            .flatten()
49    }
50}
51
52impl FromIterator<HeaderName> for AccessControlAllowHeaders {
53    fn from_iter<I>(iter: I) -> Self
54    where
55        I: IntoIterator<Item = HeaderName>,
56    {
57        let flat = iter.into_iter().map(HeaderValue::from).collect();
58        AccessControlAllowHeaders(flat)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::super::{test_decode, test_encode};
65    use super::*;
66
67    #[test]
68    fn iter() {
69        let allow_headers = test_decode::<AccessControlAllowHeaders>(&["foo, bar"]).unwrap();
70
71        let as_vec = allow_headers.iter().collect::<Vec<_>>();
72        assert_eq!(as_vec.len(), 2);
73        assert_eq!(as_vec[0], "foo");
74        assert_eq!(as_vec[1], "bar");
75    }
76
77    #[test]
78    fn from_iter() {
79        let allow: AccessControlAllowHeaders = vec![
80            ::rama_http_types::header::CACHE_CONTROL,
81            ::rama_http_types::header::IF_RANGE,
82        ]
83        .into_iter()
84        .collect();
85
86        let headers = test_encode(allow);
87        assert_eq!(
88            headers["access-control-allow-headers"],
89            "cache-control, if-range"
90        );
91    }
92
93    #[test]
94    fn test_with_invalid() {
95        let allow_headers = test_decode::<AccessControlAllowHeaders>(&["foo foo, bar"]).unwrap();
96
97        assert!(allow_headers.iter().collect::<Vec<_>>().is_empty());
98    }
99}