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
extern crate 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 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() {
}
}