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 super::cookies;
use Request;
#[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())]
);
}
}