use std::collections::HashMap;
#[derive(Clone, Debug)]
pub struct HttpHeaders {
pub pairs: HashMap<String, Vec<String>>,
pub lower_map: HashMap<String, String>,
}
impl HttpHeaders {
pub fn new() -> Self {
Self {
pairs: HashMap::new(),
lower_map: HashMap::new(),
}
}
pub fn from_vec(header_lines: &Vec<String>) -> Self {
let mut pairs: HashMap<String, Vec<String>> = HashMap::new();
let mut lower_map: HashMap<String, String> = HashMap::new();
for line in header_lines {
if let Some(cindex) = line.find(':') {
let key = line[..cindex].to_string();
pairs
.entry(key.clone())
.or_default()
.push(line[cindex + 1..].trim().to_string());
lower_map.insert(key.to_lowercase(), key);
}
}
Self { pairs, lower_map }
}
pub fn from_hash(headers: &HashMap<&str, &str>) -> Self {
let pairs: HashMap<String, Vec<String>> = headers
.iter()
.map(|(k, v)| {
let value: Vec<String> = v.split(';').map(|e| e.trim().to_string()).collect();
(k.to_string(), value)
})
.collect();
let lower_map: HashMap<String, String> = headers
.keys()
.map(|k| (k.to_lowercase().to_string(), k.to_string()))
.collect();
Self { pairs, lower_map }
}
pub fn has(&self, key: &str) -> bool {
self.pairs.contains_key(&key.to_string())
}
pub fn has_lower(&self, key: &str) -> bool {
if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
return self.has(hdr_key);
}
false
}
pub fn get(&self, key: &str) -> Option<String> {
self.pairs.get(key).and_then(|val| val.get(0)).cloned()
}
pub fn get_lower(&self, key: &str) -> Option<String> {
if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
return self.get(hdr_key);
}
None
}
pub fn get_vec(&self, key: &str) -> Vec<String> {
if let Some(values) = self.pairs.get(key) {
return values.clone();
}
vec![]
}
pub fn get_lower_vec(&self, key: &str) -> Vec<String> {
if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
return self.get_vec(hdr_key);
}
vec![]
}
pub fn get_line(&self, key: &str) -> Option<String> {
if let Some(val) = self.pairs.get(key) {
return Some(val.join("; "));
}
None
}
pub fn get_lower_line(&self, key: &str) -> Option<String> {
if let Some(hdr_key) = self.lower_map.get(key.to_lowercase().as_str()) {
return self.get_line(hdr_key);
}
None
}
pub fn all(&self) -> HashMap<String, Vec<String>> {
self.pairs.clone()
}
pub fn set(&mut self, key: &str, value: &str) {
let val = vec![value.to_string()];
*self.pairs.entry(key.to_string()).or_insert(val) = val.clone();
*self
.lower_map
.entry(key.to_lowercase().to_string())
.or_insert(key.to_string()) = key.to_string();
}
pub fn set_vec(&mut self, key: &str, value: &Vec<&str>) {
let val = value.iter().map(|s| s.to_string()).collect();
*self.pairs.entry(key.to_string()).or_insert(val) = val.clone();
*self
.lower_map
.entry(key.to_lowercase().to_string())
.or_insert(key.to_string()) = key.to_string();
}
pub fn add(&mut self, key: &str, value: &str) {
self.pairs
.entry(key.to_string())
.or_default()
.push(value.to_string());
*self
.lower_map
.entry(key.to_lowercase().to_string())
.or_insert(key.to_string()) = key.to_string();
}
pub fn delete(&mut self, key: &str) {
self.lower_map.remove(&key.to_lowercase().to_string());
self.pairs.remove(&key.to_string());
}
pub fn clear(&mut self) {
self.pairs.clear();
self.lower_map.clear();
}
}