1pub struct Headers {
2 pub vec: HeadersType,
3}
4
5pub type HeaderType = (String, String);
6pub type HeadersType = Vec<HeaderType>;
7
8pub static DISALLOWED_TRAILERS: [&'static str; 34] = [
9 "authorization",
11 "www-authenticate",
12 "proxy-authenticate",
13 "proxy-authorization",
14 "set-cookie",
15 "cookie",
16 "cookie2",
17 "access-control-allow-origin",
18 "access-control-allow-headers",
19
20 "transfer-encoding",
22 "content-length",
23 "trailer",
24 "location",
25 "vary",
26 "retry-after",
27 "content-encoding",
28 "accept-encoding",
29 "content-type",
30 "content-range",
31 "keep-alive",
32 "upgrade",
33
34 "cache-control",
36 "expect",
37 "max-forwards",
38 "pragma",
39 "range",
40 "te",
41 "expect",
42 "dnt",
43 "feature-policy",
44 "via",
45
46 "host",
48 "connection",
49 "origin",
50
51];
52
53
54impl Headers {
55 pub fn empty() -> Headers {
56 Headers { vec: vec!() }
57 }
58
59 pub fn from(pairs: Vec<(&str, &str)>) -> Headers {
60 let mut headers = Headers { vec: vec!() };
61 for pair in pairs {
62 headers = headers.add(pair)
63 }
64 headers
65 }
66
67 pub fn from_headers(headers: &Headers) -> Headers {
68 let mut new = Headers { vec: vec!() };
69 for pair in &headers.vec {
70 new = new.add((pair.0.as_str(), pair.1.as_str()))
71 }
72 new
73 }
74
75 pub fn add(&self, header: (&str, &str)) -> Headers {
76 let mut new: HeadersType = vec!();
77 let mut exists = false;
78 for existing in &self.vec {
79 if existing.0.to_lowercase() == header.0.to_lowercase() {
80 let string = existing.clone().1.to_string() + ", " + header.1;
81 new.push((existing.clone().0, string.clone()));
82 exists = true
83 } else {
84 new.push(existing.clone())
85 }
86 }
87 if !exists {
88 new.push((header.0.to_string(), header.1.to_string()))
89 }
90 Headers { vec: new }
91 }
92
93 pub fn ensure(&self, header: (&str, &str)) -> Headers {
94 if !self.has(header.0) {
95 self.add(header)
96 } else {
97 Headers::add_all(self, Headers::empty())
98 }
99 }
100
101 pub fn add_all(&self, headers: Headers) -> Headers {
102 let mut new = Headers::empty();
103 headers.vec.iter().for_each(|x| {
104 new = new.add((x.0.as_str(), x.1.as_str()))
105 });
106 self.vec.iter().for_each(|x| {
107 new = new.add((x.0.as_str(), x.1.as_str()))
108 });
109 new
110 }
111
112 pub fn replace(&self, replacing: (&str, &str)) -> Headers {
113 let mut new: HeadersType = vec!();
114 let mut exists = false;
115 for existing in &self.vec {
116 if existing.0.to_lowercase() == replacing.0.to_lowercase() {
117 new.push((existing.clone().0, replacing.1.to_string()));
118 exists = true
119 } else {
120 new.push((existing.0.to_string(), existing.1.to_string()))
121 }
122 }
123 if !exists {
124 new.push((replacing.0.to_string(), replacing.1.to_string()));
125 }
126 Headers { vec: new }
127 }
128
129 pub fn remove(&self, name: &str) -> Headers {
130 let mut new: HeadersType = vec!();
131 for existing in &self.vec {
132 if existing.0.to_lowercase() == name.to_lowercase() {} else {
133 new.push((existing.0.to_string(), existing.1.to_string()))
134 }
135 }
136 Headers { vec: new }
137 }
138
139 pub fn get(&self, name: &str) -> Option<String> {
140 for header in &self.vec {
141 if header.0.to_lowercase() == name.to_lowercase() {
142 return Some(header.1.to_string());
143 }
144 }
145 None
146 }
147
148 pub fn filter(&self, names: Vec<&str>) -> Headers {
149 let mut vec = vec!();
150 for name in names {
151 if let Some(value) = self.get(name) {
152 vec.push((name.to_string(), value) as HeaderType);
153 }
154 }
155 Headers { vec }
156 }
157
158 pub fn is_empty(&self) -> bool {
159 self.vec.is_empty()
160 }
161
162 pub fn has(&self, header_name: &str) -> bool {
163 return self.get(header_name).is_some();
164 }
165
166 pub fn content_length_header(&self) -> Option<Result<usize, String>> {
167 let value = self.get("Content-Length");
168 let value = Self::parse_or_else_value(value);
169 match value {
170 Some(Err(ref header_value)) => {
171 let split = header_value.split(", ").map(|it| it.to_string()).collect::<Vec<String>>();
172 let first = split.first().map(|it| it.to_string());
173 if split.iter().all(|v| v == first.as_ref().unwrap()) {
174 Self::parse_or_else_value(first)
175 } else {
176 value.clone()
177 }
178 }
179 _ => value
180 }
181 }
182
183 fn parse_or_else_value(value: Option<String>) -> Option<Result<usize, String>> {
184 value.as_ref().map(|x| x.parse::<usize>())
185 .map(|r| r.map_err(|_| value.unwrap()))
186 }
187
188 pub fn parse_from(header_string: &str) -> Headers {
189 if header_string.is_empty() {
190 return Headers::empty();
191 }
192 header_string.split("\r\n").fold(Headers::empty(), |acc, pair| {
193 let pair = pair.split(": ").collect::<Vec<&str>>();
194
195 acc.add((pair[0], pair[1]))
196 })
197 }
198
199 pub fn to_wire_string(&self) -> String {
200 self.vec.iter().map(|h| {
201 let clone = h.clone();
202 clone.0.to_owned() + ": " + clone.1.as_str()
203 }).collect::<Vec<String>>()
204 .join("\r\n")
205 }
206
207 pub fn js_headers_from_string(str: &str) -> Headers {
208 str.split("; ").fold(Headers::empty(), |acc: Headers, next: &str| {
209 let mut split = next.split(": ");
210 acc.add((split.next().unwrap(), split.next().unwrap()))
211 })
212 }
213
214 pub fn js_headers_to_string(headers: &HeadersType) -> String {
215 headers.iter().map(|h| {
216 let clone = h.clone();
217 clone.0 + ": " + clone.1.as_str()
218 }).collect::<Vec<String>>()
219 .join("; ")
220 }
221}
222
223pub fn content_type_header(value: &str) -> (&'static str, &str) {
224 ("Content-Type", value)
225}
226
227pub fn cache_control_header(value: &str) -> (&'static str, &str) { ("Cache-Control", value) }
228
229pub fn content_length_header(value: &str) -> (&'static str, &str) { ("Content-Length", value) }