tower_http/cors/
vary.rs

1use http::header::{self, HeaderName, HeaderValue};
2
3use super::preflight_request_headers;
4
5/// Holds configuration for how to set the [`Vary`][mdn] header.
6///
7/// See [`CorsLayer::vary`] for more details.
8///
9/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
10/// [`CorsLayer::vary`]: super::CorsLayer::vary
11#[derive(Clone, Debug)]
12pub struct Vary(Vec<HeaderValue>);
13
14impl Vary {
15    /// Set the list of header names to return as vary header values
16    ///
17    /// See [`CorsLayer::vary`] for more details.
18    ///
19    /// [`CorsLayer::vary`]: super::CorsLayer::vary
20    pub fn list<I>(headers: I) -> Self
21    where
22        I: IntoIterator<Item = HeaderName>,
23    {
24        Self(headers.into_iter().map(Into::into).collect())
25    }
26
27    pub(super) fn to_header(&self) -> Option<(HeaderName, HeaderValue)> {
28        let values = &self.0;
29        let mut res = values.first()?.as_bytes().to_owned();
30        for val in &values[1..] {
31            res.extend_from_slice(b", ");
32            res.extend_from_slice(val.as_bytes());
33        }
34
35        let header_val = HeaderValue::from_bytes(&res)
36            .expect("comma-separated list of HeaderValues is always a valid HeaderValue");
37        Some((header::VARY, header_val))
38    }
39}
40
41impl Default for Vary {
42    fn default() -> Self {
43        Self::list(preflight_request_headers())
44    }
45}
46
47impl<const N: usize> From<[HeaderName; N]> for Vary {
48    fn from(arr: [HeaderName; N]) -> Self {
49        Self::list(arr)
50    }
51}
52
53impl From<Vec<HeaderName>> for Vary {
54    fn from(vec: Vec<HeaderName>) -> Self {
55        Self::list(vec)
56    }
57}