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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
extern crate cookie as _cookie;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate iron;
extern crate rand;
#[cfg(feature = "redis-backend")] extern crate redis;
#[cfg(feature = "redis-backend")] extern crate r2d2;
#[cfg(feature = "redis-backend")] extern crate r2d2_redis;
use iron::prelude::*;
use iron::middleware::{AroundMiddleware,Handler};
use iron::typemap;
pub mod backends;
pub mod errors;
pub mod cookie {
pub use _cookie::*;
}
pub trait RawSession {
fn get_raw(&self, key: &str) -> IronResult<Option<String>>;
fn set_raw(&mut self, key: &str, value: String) -> IronResult<()>;
fn clear(&mut self) -> IronResult<()>;
fn write(&self, response: &mut Response) -> IronResult<()>;
}
pub trait SessionBackend: Send + Sync + 'static {
type S: RawSession;
fn from_request(&self, request: &mut Request) -> Self::S;
}
pub struct SessionStorage<B: SessionBackend> {
backend: B
}
impl<B: SessionBackend> SessionStorage<B> {
pub fn new(backend: B) -> Self {
SessionStorage {
backend: backend
}
}
}
pub struct Session {
inner: Box<RawSession>
}
pub trait Value: Sized + 'static {
fn get_key() -> &'static str;
fn into_raw(self) -> String;
fn from_raw(value: String) -> Option<Self>;
}
impl Session {
pub fn get<T: Value + Sized + 'static>(&self) -> IronResult<Option<T>> {
Ok(try!(self.inner.get_raw(T::get_key())).and_then(T::from_raw))
}
pub fn set<T: Value>(&mut self, t: T) -> IronResult<()> {
self.inner.set_raw(T::get_key(), t.into_raw())
}
pub fn clear(&mut self) -> IronResult<()> {
self.inner.clear()
}
}
struct SessionKey;
impl typemap::Key for SessionKey { type Value = Session; }
impl<B: SessionBackend> AroundMiddleware for SessionStorage<B> {
fn around(self, handler: Box<Handler>) -> Box<Handler> {
Box::new(move |req: &mut Request| -> IronResult<Response> {
let s = self.backend.from_request(req);
req.extensions.insert::<SessionKey>(Session {
inner: Box::new(s)
});
let mut res = handler.handle(req);
let s = req.extensions.remove::<SessionKey>().unwrap();
match res {
Ok(ref mut x) => try!(s.inner.write(x)),
Err(ref mut e) => try!(s.inner.write(&mut e.response))
};
res
})
}
}
pub trait SessionRequestExt {
fn session(&mut self) -> &mut Session;
}
impl<'a, 'b> SessionRequestExt for Request<'a, 'b> {
fn session(&mut self) -> &mut Session {
self.extensions.get_mut::<SessionKey>().unwrap()
}
}
pub mod traits {
pub use super::{SessionRequestExt};
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
}
}