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
110
use std::str::Split;
use Request;
pub fn cookies(request: &Request) -> CookiesIter {
let header = match request.header("Cookie") {
None => "",
Some(h) => h,
};
CookiesIter {
iter: header.split(';')
}
}
pub struct CookiesIter<'a> {
iter: Split<'a, char>,
}
impl<'a> Iterator for CookiesIter<'a> {
type Item = (&'a str, &'a str);
fn next(&mut self) -> Option<Self::Item> {
loop {
let cookie = match self.iter.next() {
Some(c) => c,
None => return None
};
let mut splits = cookie.splitn(2, |c| c == '=');
let key = match splits.next() { None => continue, Some(v) => v };
let value = match splits.next() { None => continue, Some(v) => v };
let key = key.trim();
let value = value.trim().trim_matches(|c| c == '"');
return Some((key, value));
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, len) = self.iter.size_hint();
(0, len)
}
}
#[cfg(test)]
mod test {
use Request;
use super::cookies;
#[test]
fn no_cookie() {
let request = Request::fake_http("GET", "/", vec![], Vec::new());
assert_eq!(cookies(&request).count(), 0);
}
#[test]
fn cookies_ok() {
let request = Request::fake_http("GET", "/",
vec![("Cookie".to_owned(),
"a=b; hello=world".to_owned())],
Vec::new());
assert_eq!(cookies(&request).collect::<Vec<_>>(), vec![
("a".into(), "b".into()),
("hello".into(), "world".into())
]);
}
}