atlas_http/
headers.rs

1
2use std::collections::HashMap;
3
4#[derive(Clone, Debug)]
5pub struct HttpHeaders {
6    pairs: HashMap<String, Vec<String>>,
7    lower_map: HashMap<String, String>,
8}
9
10
11impl HttpHeaders {
12    /// Generate blank instance of struct.
13    pub fn new() -> Self {
14        Self {
15            pairs: HashMap::new(),
16            lower_map: HashMap::new(),
17        }
18    }
19
20    /// Parse lines from HTTP response into struct.
21    pub fn from_vec(header_lines: &Vec<String>) -> Self {
22        // Initialize
23        let mut pairs: HashMap<String, Vec<String>> = HashMap::new();
24        let mut lower_map: HashMap<String, String> = HashMap::new();
25
26        // GO through lines
27        for line in header_lines {
28            if let Some(cindex) = line.find(':') {
29                let key = line[..cindex].to_string();
30                pairs
31                    .entry(key.clone())
32                    .or_default()
33                    .push(line[cindex + 1..].trim().to_string());
34                lower_map.insert(key.to_lowercase(), key);
35            }
36        }
37
38        Self { pairs, lower_map }
39    }
40
41    /// Create headers instance from hashmap
42    pub fn from_hash(headers: &HashMap<&str, &str>) -> Self {
43        let pairs: HashMap<String, Vec<String>> = headers
44            .iter()
45            .map(|(k, v)| {
46                let value: Vec<String> = v.split(';').map(|e| e.trim().to_string()).collect();
47                (k.to_string(), value)
48            })
49            .collect();
50
51        let lower_map: HashMap<String, String> = headers
52            .keys()
53            .map(|k| (k.to_lowercase().to_string(), k.to_string()))
54            .collect();
55
56        Self { pairs, lower_map }
57    }
58
59    // Check whether or not header exists, case-sensitive
60    pub fn has(&self, key: &str) -> bool {
61        self.pairs.contains_key(&key.to_string())
62    }
63
64    // Check whether or not header exists, case-insensitive
65    pub fn has_lower(&self, key: &str) -> bool {
66        if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
67            return self.has(hdr_key);
68        }
69        false
70    }
71
72    /// Get value of HTTP header.  Case-sensitive, will
73    /// only return first instance if multiple instances of same key exist.
74    pub fn get(&self, key: &str) -> Option<String> {
75        self.pairs.get(key).and_then(|val| val.get(0)).cloned()
76    }
77
78    /// Get value of HTTP header.  Same as get(), but case-insensitive.
79    pub fn get_lower(&self, key: &str) -> Option<String> {
80        if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
81            return self.get(hdr_key);
82        }
83        None
84    }
85
86    /// Get vector of all values of header, case-sensitive.
87    pub fn get_vec(&self, key: &str) -> Vec<String> {
88        if let Some(values) = self.pairs.get(key) {
89            return values.clone();
90        }
91        vec![]
92    }
93
94    // Get vector of all values of header, case-insensitive.
95    pub fn get_lower_vec(&self, key: &str) -> Vec<String> {
96        if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
97            return self.get_vec(hdr_key);
98        }
99        vec![]
100    }
101
102    /// Get header line, all values delimited by ";", case-sensitive.
103    pub fn get_line(&self, key: &str) -> Option<String> {
104        if let Some(val) = self.pairs.get(key) {
105            return Some(val.join("; "));
106        }
107        None
108    }
109
110    /// Get header line, all values delimited by ";", case-sensitive.
111    pub fn get_lower_line(&self, key: &str) -> Option<String> {
112        if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
113            return self.get_line(hdr_key);
114        }
115        None
116    }
117
118    /// Get all headers as hashmap
119    pub fn all(&self) -> HashMap<String, Vec<String>> {
120        self.pairs.clone()
121    }
122
123    /// Set header, replacing any existing header value with same key
124    pub fn set(&mut self, key: &str, value: &str) {
125        let val = vec![value.to_string()];
126        *self.pairs.entry(key.to_string()).or_insert(val) = val.clone();
127        *self
128            .lower_map
129            .entry(key.to_lowercase().to_string())
130            .or_insert(key.to_string()) = key.to_string();
131    }
132
133    /// Set header, replacing any existing header value with same key
134    pub fn set_vec(&mut self, key: &str, value: &Vec<&str>) {
135        let val = value.iter().map(|s| s.to_string()).collect();
136        *self.pairs.entry(key.to_string()).or_insert(val) = val.clone();
137        *self
138            .lower_map
139            .entry(key.to_lowercase().to_string())
140            .or_insert(key.to_string()) = key.to_string();
141    }
142
143    /// Add value to existing header, or add new header if key non-existent.
144    pub fn add(&mut self, key: &str, value: &str) {
145        self.pairs
146            .entry(key.to_string())
147            .or_default()
148            .push(value.to_string());
149        *self
150            .lower_map
151            .entry(key.to_lowercase().to_string())
152            .or_insert(key.to_string()) = key.to_string();
153    }
154
155    /// Delete header
156    pub fn delete(&mut self, key: &str) {
157        self.lower_map.remove(&key.to_lowercase().to_string());
158        self.pairs.remove(&key.to_string());
159    }
160
161    /// Clear / purge all headers
162    pub fn clear(&mut self) {
163        self.pairs.clear();
164        self.lower_map.clear();
165    }
166}