snx/http/header.rs
1use std::{collections::HashMap, ops::Deref};
2
3/// A multimap of HTTP headers to values.
4///
5/// Header names are case-insensitive.
6#[derive(Clone, Default, Debug)]
7pub struct HeaderMap(HashMap<String, Vec<String>>);
8
9impl HeaderMap {
10 /// Creates a new header map.
11 pub fn new() -> Self {
12 Self::default()
13 }
14
15 /// Inserts a header.
16 ///
17 /// ```
18 /// use snx::HeaderMap;
19 ///
20 /// let mut headers = HeaderMap::new();
21 /// headers.insert("Content-Type", "application/json");
22 /// ```
23 pub fn insert(&mut self, name: &str, value: &str) {
24 match self.0.get_mut(name) {
25 Some(values) => values.push(value.to_string()),
26 None => {
27 self.0.insert(name.to_lowercase(), vec![value.to_string()]);
28 }
29 }
30 }
31
32 /// Gets the first value of a header if it exists.
33 ///
34 /// ```
35 /// use snx::HeaderMap;
36 ///
37 /// let mut headers = HeaderMap::new();
38 /// headers.insert("Content-Type", "application/json");
39 ///
40 /// let content_type = headers.get("Content-Type").unwrap();
41 /// ```
42 pub fn get(&self, name: &str) -> Option<String> {
43 self.0.get(&name.to_lowercase())?.first().cloned()
44 }
45
46 /// Gets all values of a header.
47 ///
48 /// ```
49 /// use snx::HeaderMap;
50 ///
51 /// let mut headers = HeaderMap::new();
52 /// headers.insert("Transfer-Encoding", "chunked");
53 /// headers.insert("Transfer-Encoding", "gzip");
54 ///
55 /// let encodings = headers.get_all("Transfer-Encoding").unwrap();
56 /// ```
57 pub fn get_all(&self, name: &str) -> Option<Vec<String>> {
58 self.0.get(&name.to_lowercase()).cloned()
59 }
60}
61
62impl From<(&str, &str)> for HeaderMap {
63 fn from(val: (&str, &str)) -> Self {
64 let mut map = HeaderMap::new();
65
66 map.insert(&val.0.to_lowercase(), val.1);
67
68 map
69 }
70}
71
72impl Deref for HeaderMap {
73 type Target = HashMap<String, Vec<String>>;
74
75 fn deref(&self) -> &Self::Target {
76 &self.0
77 }
78}