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