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
use iron;

pub use hyper::header::{CookiePair as Cookie, CookieJar};
use backend::{self, Request};
use server::header;
use ::{Extensible};

struct CookieJarKey;

impl ::typemap::Key for CookieJarKey {
    type Value = CookieJar<'static>;
}

pub trait CookieExt {
    fn find_cookie_jar(&mut self) -> Option<&mut CookieJar<'static>>;
    fn store_cookie_jar(&mut self, jar: CookieJar<'static>);
    fn cookies<'a>(&'a mut self) -> &'a mut CookieJar<'static> {
        self.find_cookie_jar().unwrap()
    }
}

impl<'r> CookieExt for (backend::Request + 'r) {
    fn find_cookie_jar<'a>(&'a mut self) -> Option<&'a mut CookieJar<'static>> {
        self.ext_mut().get_mut::<CookieJarKey>()
    }

    fn store_cookie_jar(&mut self, jar: CookieJar<'static>) {
        self.ext_mut().insert::<CookieJarKey>(jar);
    }
}

pub struct CookieDecodeMiddleware {
    secret_token: Vec<u8>
}

impl iron::BeforeMiddleware for CookieDecodeMiddleware {
    fn before(&self, req: &mut iron::Request) -> iron::IronResult<()> {
        let token = &self.secret_token;
        let jar = req.headers().get::<header::Cookie>()
            .map(|cookies| cookies.to_cookie_jar(token))
            .unwrap_or_else(|| CookieJar::new(token));

        req.ext_mut().insert::<CookieJarKey>(jar);
        Ok(())
    }
}

#[allow(missing_copy_implementations)]
pub struct CookieEncodeMiddleware;

impl iron::AfterMiddleware for CookieEncodeMiddleware {
    fn after(&self, req: &mut iron::Request, mut res: iron::Response) -> iron::IronResult<iron::Response> {
        let maybe_jar = (req as &mut backend::Request).find_cookie_jar();
        match maybe_jar {
            Some(jar) => {
                res.headers.set(header::SetCookie::from_cookie_jar(jar));
            },
            None => ()
        }

        Ok(res)
    }
}

pub fn new(secret_token: &[u8]) -> (CookieDecodeMiddleware, CookieEncodeMiddleware) {
    (
        CookieDecodeMiddleware{secret_token: secret_token.to_vec()},
        CookieEncodeMiddleware
    )
}