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
use crate::cookie;
use crate::http::{header, HeaderValue, Response};
use cookie::Cookie;
use derive_more::{Display, From};
use std::collections::HashMap;

#[derive(Debug, Display, From)]
pub enum ResponseError {
    #[display(fmt = "header value (`{:?}`) is not string: {}", value, msg)]
    HeaderValueNotStr {
        value: HeaderValue,
        msg: header::ToStrError,
    },

    #[display(fmt = "parse cookie('{}') error: {}", value, msg)]
    ParseCookieError {
        value: String,
        msg: cookie::ParseError,
    },
}

pub trait ResponseExt {
    fn cookies(&self) -> Result<Vec<Cookie>, ResponseError>;
    fn cookie_map(&self) -> Result<HashMap<String, Vec<Cookie>>, ResponseError>;
}

impl<T> ResponseExt for Response<T> {
    fn cookies(&self) -> Result<Vec<Cookie>, ResponseError> {
        let mut cookies = Vec::new();
        for cookie in self.headers().get_all(header::SET_COOKIE) {
            let cookie_str = cookie.to_str().map_err(|err| (cookie.clone(), err))?;
            cookies.push(Cookie::parse(cookie_str).map_err(|err| (cookie_str.to_owned(), err))?)
        }
        Ok(cookies)
    }

    fn cookie_map(&self) -> Result<HashMap<String, Vec<Cookie>>, ResponseError> {
        let mut map = HashMap::new();
        for cookie in self.headers().get_all(header::SET_COOKIE) {
            let cookie_str = cookie.to_str().map_err(|err| (cookie.clone(), err))?;
            let cookie = Cookie::parse(cookie_str).map_err(|err| (cookie_str.to_owned(), err))?;
            match map.get_mut(cookie.name()) {
                None => {
                    map.insert(cookie.name().to_owned(), vec![cookie]);
                }
                Some(list) => list.push(cookie),
            }
        }
        Ok(map)
    }
}