http_types_2/headers/
headers.rs

1//! HTTP headers.
2
3use std::collections::HashMap;
4use std::convert::Into;
5use std::fmt::{self, Debug};
6use std::iter::IntoIterator;
7use std::ops::Index;
8use std::str::FromStr;
9
10use crate::headers::{
11    HeaderName, HeaderValues, IntoIter, Iter, IterMut, Names, ToHeaderValues, Values,
12};
13
14/// A collection of HTTP Headers.
15///
16/// Headers are never manually constructed, but are part of `Request`,
17/// `Response`, and `Trailers`. Each of these types implements `AsRef<Headers>`
18/// and `AsMut<Headers>` so functions that want to modify headers can be generic
19/// over either of these traits.
20///
21/// # Examples
22///
23/// ```
24/// use http_types::{Response, StatusCode};
25///
26/// let mut res = Response::new(StatusCode::Ok);
27/// res.insert_header("hello", "foo0");
28/// assert_eq!(res["hello"], "foo0");
29/// ```
30#[derive(Clone)]
31pub struct Headers {
32    pub(crate) headers: HashMap<HeaderName, HeaderValues>,
33}
34
35impl Headers {
36    /// Create a new instance.
37    pub(crate) fn new() -> Self {
38        Self {
39            headers: HashMap::new(),
40        }
41    }
42
43    /// Insert a header into the headers.
44    ///
45    /// Not that this will replace all header values for a given header name.
46    /// If you wish to add header values for a header name that already exists
47    /// use `Headers::append`
48    pub fn insert(
49        &mut self,
50        name: impl Into<HeaderName>,
51        values: impl ToHeaderValues,
52    ) -> crate::Result<Option<HeaderValues>> {
53        let name = name.into();
54        let values: HeaderValues = values.to_header_values()?.collect();
55        Ok(self.headers.insert(name, values))
56    }
57
58    /// Append a header to the headers.
59    ///
60    /// Unlike `insert` this function will not override the contents of a header, but insert a
61    /// header if there aren't any. Or else append to the existing list of headers.
62    pub fn append(
63        &mut self,
64        name: impl Into<HeaderName>,
65        values: impl ToHeaderValues,
66    ) -> crate::Result<()> {
67        let name = name.into();
68        match self.get_mut(&name) {
69            Some(headers) => {
70                let mut values: HeaderValues = values.to_header_values()?.collect();
71                headers.append(&mut values);
72            }
73            None => {
74                self.insert(name, values)?;
75            }
76        }
77        Ok(())
78    }
79
80    /// Get a reference to a header.
81    pub fn get(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
82        self.headers.get(&name.into())
83    }
84
85    /// Get a mutable reference to a header.
86    pub fn get_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
87        self.headers.get_mut(&name.into())
88    }
89
90    /// Remove a header.
91    pub fn remove(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
92        self.headers.remove(&name.into())
93    }
94
95    /// An iterator visiting all header pairs in arbitrary order.
96    pub fn iter(&self) -> Iter<'_> {
97        Iter {
98            inner: self.headers.iter(),
99        }
100    }
101
102    /// An iterator visiting all header pairs in arbitrary order, with mutable references to the
103    /// values.
104    pub fn iter_mut(&mut self) -> IterMut<'_> {
105        IterMut {
106            inner: self.headers.iter_mut(),
107        }
108    }
109
110    /// An iterator visiting all header names in arbitrary order.
111    pub fn names(&self) -> Names<'_> {
112        Names {
113            inner: self.headers.keys(),
114        }
115    }
116
117    /// An iterator visiting all header values in arbitrary order.
118    pub fn values(&self) -> Values<'_> {
119        Values::new(self.headers.values())
120    }
121}
122
123impl Index<HeaderName> for Headers {
124    type Output = HeaderValues;
125
126    /// Returns a reference to the value corresponding to the supplied name.
127    ///
128    /// # Panics
129    ///
130    /// Panics if the name is not present in `Headers`.
131    #[inline]
132    fn index(&self, name: HeaderName) -> &HeaderValues {
133        self.get(name).expect("no entry found for name")
134    }
135}
136
137impl Index<&str> for Headers {
138    type Output = HeaderValues;
139
140    /// Returns a reference to the value corresponding to the supplied name.
141    ///
142    /// # Panics
143    ///
144    /// Panics if the name is not present in `Headers`.
145    #[inline]
146    fn index(&self, name: &str) -> &HeaderValues {
147        let name = HeaderName::from_str(name).expect("string slice needs to be valid ASCII");
148        self.get(name).expect("no entry found for name")
149    }
150}
151
152impl IntoIterator for Headers {
153    type Item = (HeaderName, HeaderValues);
154    type IntoIter = IntoIter;
155
156    /// Returns a iterator of references over the remaining items.
157    #[inline]
158    fn into_iter(self) -> Self::IntoIter {
159        IntoIter {
160            inner: self.headers.into_iter(),
161        }
162    }
163}
164
165impl<'a> IntoIterator for &'a Headers {
166    type Item = (&'a HeaderName, &'a HeaderValues);
167    type IntoIter = Iter<'a>;
168
169    #[inline]
170    fn into_iter(self) -> Self::IntoIter {
171        self.iter()
172    }
173}
174
175impl<'a> IntoIterator for &'a mut Headers {
176    type Item = (&'a HeaderName, &'a mut HeaderValues);
177    type IntoIter = IterMut<'a>;
178
179    #[inline]
180    fn into_iter(self) -> Self::IntoIter {
181        self.iter_mut()
182    }
183}
184
185impl Debug for Headers {
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        f.debug_map().entries(self.headers.iter()).finish()
188    }
189}
190
191impl AsRef<Headers> for Headers {
192    fn as_ref(&self) -> &Headers {
193        self
194    }
195}
196
197impl AsMut<Headers> for Headers {
198    fn as_mut(&mut self) -> &mut Headers {
199        self
200    }
201}
202
203#[cfg(test)]
204mod tests {
205    use super::*;
206    use std::str::FromStr;
207
208    const STATIC_HEADER: HeaderName = HeaderName::from_lowercase_str("hello");
209
210    #[test]
211    fn test_header_name_static_non_static() -> crate::Result<()> {
212        let static_header = HeaderName::from_lowercase_str("hello");
213        let non_static_header = HeaderName::from_str("hello")?;
214
215        let mut headers = Headers::new();
216        headers.append(STATIC_HEADER, "foo0").unwrap();
217        headers.append(static_header.clone(), "foo1").unwrap();
218        headers.append(non_static_header.clone(), "foo2").unwrap();
219
220        assert_eq!(headers[STATIC_HEADER], ["foo0", "foo1", "foo2",][..]);
221        assert_eq!(headers[static_header], ["foo0", "foo1", "foo2",][..]);
222        assert_eq!(headers[non_static_header], ["foo0", "foo1", "foo2",][..]);
223
224        Ok(())
225    }
226
227    #[test]
228    fn index_into_headers() {
229        let mut headers = Headers::new();
230        headers.insert("hello", "foo0").unwrap();
231        assert_eq!(headers["hello"], "foo0");
232        assert_eq!(headers.get("hello").unwrap(), "foo0");
233    }
234
235    #[test]
236    fn test_debug_single() {
237        let mut headers = Headers::new();
238        headers.insert("single", "foo0").unwrap();
239        assert_eq!(format!("{headers:?}"), r#"{"single": "foo0"}"#);
240    }
241
242    #[test]
243    fn test_debug_multiple() {
244        let mut headers = Headers::new();
245        headers.append("multi", "foo0").unwrap();
246        headers.append("multi", "foo1").unwrap();
247        assert_eq!(format!("{headers:?}"), r#"{"multi": ["foo0", "foo1"]}"#);
248    }
249}