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