1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! HTTP request headers.
use std::collections::{hash_map::Iter, HashMap};
/// HTTP headers.
#[derive(Clone, Debug, Default)]
pub struct Headers {
headers: HashMap<String, String>,
}
impl Headers {
/// Create new empty headers storage.
pub fn new() -> Self {
Self {
headers: HashMap::new(),
}
}
/// Add a header to the headers storage. The name will be converted to lowercase.
///
/// # Example
///
/// ```
/// # use rwf::http::Headers;
/// let mut headers = Headers::new();
/// headers.insert("x-my-header", "134");
/// ```
///
/// #### Implementation note
///
/// This implementation doesn't support adding
/// multiple headers with the same name. This is
/// only needed for the `Set-Cookie` header which
/// is handled separately.
pub fn insert(&mut self, name: impl ToString, value: impl ToString) {
self.headers
.insert(name.to_string().to_lowercase(), value.to_string());
}
/// Get a header value by name. Case insensitive.
///
/// # Example
///
/// ```
/// # use rwf::http::Headers;
/// # let mut headers = Headers::new();
/// # headers.insert("x-my-header", "134");
/// let header = headers.get("x-my-header");
/// assert_eq!(header, Some(&String::from("134")));
/// ```
pub fn get(&self, name: &str) -> Option<&String> {
self.headers.get(&name.to_lowercase())
}
/// Remove a header by name. Case insensitive.
///
/// # Example
///
/// ```
/// # use rwf::http::Headers;
/// # let mut headers = Headers::new();
/// headers.remove("x-my-header");
/// ```
pub fn remove(&mut self, name: &str) -> Option<String> {
self.headers.remove(&name.to_lowercase())
}
/// Remove all headers.
///
/// # Example
///
/// ```
/// # use rwf::http::Headers;
/// # let mut headers = Headers::new();
/// headers.clear();
/// assert!(headers.into_raw().is_empty());
/// ```
pub fn clear(&mut self) {
self.headers.clear();
}
/// Convert headers into a [`HashMap`] keyed by header name.
pub fn into_raw(self) -> HashMap<String, String> {
self.headers
}
/// Get a borrowing interator to the headers.
pub fn iter(&self) -> Iter<String, String> {
self.headers.iter()
}
/// Convert headers to bytes.
/// Used to send headers to the client.
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
for (name, value) in &self.headers {
bytes.extend_from_slice(name.as_bytes());
bytes.extend_from_slice(b": ");
bytes.extend_from_slice(value.as_bytes());
bytes.extend_from_slice(b"\r\n");
}
bytes
}
}
impl From<HashMap<String, String>> for Headers {
fn from(headers: HashMap<String, String>) -> Self {
Self { headers }
}
}