headers/common/
access_control_expose_headers.rs

1use std::iter::FromIterator;
2
3use util::FlatCsv;
4use {HeaderName, HeaderValue};
5
6/// `Access-Control-Expose-Headers` header, part of
7/// [CORS](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header)
8///
9/// The Access-Control-Expose-Headers header indicates which headers are safe to expose to the
10/// API of a CORS API specification.
11///
12/// # ABNF
13///
14/// ```text
15/// Access-Control-Expose-Headers = "Access-Control-Expose-Headers" ":" #field-name
16/// ```
17///
18/// # Example values
19/// * `ETag, Content-Length`
20///
21/// # Examples
22///
23/// ```
24/// # extern crate headers;
25/// extern crate http;
26/// # fn main() {
27/// use http::header::{CONTENT_LENGTH, ETAG};
28/// use headers::AccessControlExposeHeaders;
29///
30/// let expose = vec![CONTENT_LENGTH, ETAG]
31///     .into_iter()
32///     .collect::<AccessControlExposeHeaders>();
33/// # }
34/// ```
35#[derive(Clone, Debug)]
36pub struct AccessControlExposeHeaders(FlatCsv);
37
38derive_header! {
39    AccessControlExposeHeaders(_),
40    name: ACCESS_CONTROL_EXPOSE_HEADERS
41}
42
43impl AccessControlExposeHeaders {
44    /// Returns an iterator over `HeaderName`s contained within.
45    pub fn iter<'a>(&'a self) -> impl Iterator<Item = HeaderName> + 'a {
46        self.0.iter().filter_map(|s| s.parse().ok())
47    }
48}
49
50impl FromIterator<HeaderName> for AccessControlExposeHeaders {
51    fn from_iter<I>(iter: I) -> Self
52    where
53        I: IntoIterator<Item = HeaderName>,
54    {
55        let flat = iter.into_iter().map(HeaderValue::from).collect();
56        AccessControlExposeHeaders(flat)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::super::{test_decode, test_encode};
63    use super::*;
64
65    #[test]
66    fn iter() {
67        let expose_headers = test_decode::<AccessControlExposeHeaders>(&["foo, bar"]).unwrap();
68
69        let as_vec = expose_headers.iter().collect::<Vec<_>>();
70        assert_eq!(as_vec.len(), 2);
71        assert_eq!(as_vec[0], "foo");
72        assert_eq!(as_vec[1], "bar");
73    }
74
75    #[test]
76    fn from_iter() {
77        let expose: AccessControlExposeHeaders =
78            vec![::http::header::CACHE_CONTROL, ::http::header::IF_RANGE]
79                .into_iter()
80                .collect();
81
82        let headers = test_encode(expose);
83        assert_eq!(
84            headers["access-control-expose-headers"],
85            "cache-control, if-range"
86        );
87    }
88}