Skip to main content

rama_http_headers/common/
access_control_expose_headers.rs

1use rama_http_types::HeaderName;
2
3derive_values_or_any_header! {
4    #[header(name = ACCESS_CONTROL_EXPOSE_HEADERS, sep = Comma)]
5    #[derive(Clone, Debug)]
6    /// `Access-Control-Expose-Headers` header, as defined on
7    /// [mdn](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Expose-Headers).
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    /// # fn main() {
25    /// use rama_utils::collections::non_empty_vec;
26    /// use rama_http_types::header::{CONTENT_LENGTH, ETAG};
27    /// use rama_http_headers::AccessControlExposeHeaders;
28    ///
29    /// let expose = AccessControlExposeHeaders::new_values(
30    ///     non_empty_vec![CONTENT_LENGTH, ETAG],
31    /// );
32    /// # }
33    /// ```
34    pub struct AccessControlExposeHeaders(pub ValuesOrAny<HeaderName>);
35}
36
37#[cfg(test)]
38mod tests {
39    use super::super::{test_decode, test_encode};
40    use super::*;
41    use rama_utils::collections::non_empty_vec;
42
43    #[test]
44    fn decode_header_single() {
45        let expose_headers = test_decode::<AccessControlExposeHeaders>(&["foo, bar"])
46            .unwrap()
47            .into_values()
48            .unwrap();
49
50        assert_eq!(expose_headers.len(), 2);
51        assert_eq!(expose_headers[0], "foo");
52        assert_eq!(expose_headers[1], "bar");
53    }
54
55    #[test]
56    fn decode_any() {
57        assert!(
58            test_decode::<AccessControlExposeHeaders>(&["*"])
59                .unwrap()
60                .is_any(),
61        );
62    }
63
64    #[test]
65    fn decode_any_with_trailer_value() {
66        let expose_headers = test_decode::<AccessControlExposeHeaders>(&["*, bar"])
67            .unwrap()
68            .into_values()
69            .unwrap();
70
71        assert_eq!(expose_headers.len(), 2);
72        assert_eq!(expose_headers[0], "*");
73        assert_eq!(expose_headers[1], "bar");
74    }
75
76    #[test]
77    fn decode_any_with_trailer_header() {
78        let expose_headers = test_decode::<AccessControlExposeHeaders>(&["*", "bar"])
79            .unwrap()
80            .into_values()
81            .unwrap();
82
83        assert_eq!(expose_headers.len(), 2);
84        assert_eq!(expose_headers[0], "*");
85        assert_eq!(expose_headers[1], "bar");
86    }
87
88    #[test]
89    fn decode_header_multi() {
90        let expose_headers = test_decode::<AccessControlExposeHeaders>(&["foo, bar", "baz"])
91            .unwrap()
92            .into_values()
93            .unwrap();
94
95        assert_eq!(expose_headers.len(), 3);
96        assert_eq!(expose_headers[0], "foo");
97        assert_eq!(expose_headers[1], "bar");
98        assert_eq!(expose_headers[2], "baz");
99    }
100
101    #[test]
102    fn encode() {
103        let allow = AccessControlExposeHeaders::new_values(non_empty_vec![
104            ::rama_http_types::header::CACHE_CONTROL,
105            ::rama_http_types::header::IF_RANGE,
106        ]);
107
108        let headers = test_encode(allow);
109        assert_eq!(
110            headers["access-control-expose-headers"],
111            "cache-control, if-range"
112        );
113    }
114
115    #[test]
116    fn encode_any() {
117        let allow = AccessControlExposeHeaders::new_any();
118        let headers = test_encode(allow);
119        assert_eq!(headers["access-control-expose-headers"], "*");
120    }
121
122    #[test]
123    fn decode_with_empty_header_value() {
124        assert!(test_decode::<AccessControlExposeHeaders>(&[""]).is_none());
125    }
126
127    #[test]
128    fn decode_with_no_headers() {
129        assert!(test_decode::<AccessControlExposeHeaders>(&[]).is_none());
130    }
131
132    #[test]
133    fn decode_with_invalid_value_str() {
134        assert!(test_decode::<AccessControlExposeHeaders>(&["foo foo, bar"]).is_none());
135    }
136}