headers_ext/common/
access_control_expose_headers.rs

1use std::iter::FromIterator;
2
3use {HeaderName, HeaderValue};
4use util::FlatCsv;
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_ext as 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, Header)]
36pub struct AccessControlExposeHeaders(FlatCsv);
37
38impl AccessControlExposeHeaders {
39    /// Returns an iterator over `HeaderName`s contained within.
40    pub fn iter<'a>(&'a self) -> impl Iterator<Item = HeaderName> + 'a {
41        self
42            .0
43            .iter()
44            .filter_map(|s| {
45                s.parse().ok()
46            })
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
56            .into_iter()
57            .map(HeaderValue::from)
58            .collect();
59        AccessControlExposeHeaders(flat)
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    use super::super::{test_decode, test_encode};
67
68    #[test]
69    fn iter() {
70        let expose_headers = test_decode::<AccessControlExposeHeaders>(
71            &["foo, bar"]
72        ).unwrap();
73
74        let as_vec = expose_headers.iter().collect::<Vec<_>>();
75        assert_eq!(as_vec.len(), 2);
76        assert_eq!(as_vec[0], "foo");
77        assert_eq!(as_vec[1], "bar");
78    }
79
80    #[test]
81    fn from_iter() {
82        let expose: AccessControlExposeHeaders = vec![
83            ::http::header::CACHE_CONTROL,
84            ::http::header::IF_RANGE,
85        ].into_iter().collect();
86
87        let headers = test_encode(expose);
88        assert_eq!(headers["access-control-expose-headers"], "cache-control, if-range");
89    }
90}
91