http4r_core/
headers.rs

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
10    "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
21    "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    //controls
35    "cache-control",
36    "expect",
37    "max-forwards",
38    "pragma",
39    "range",
40    "te",
41    "expect",
42    "dnt",
43    "feature-policy",
44    "via",
45
46    //routing
47    "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) }