use futures::Future;
use plugins::{Plugin, PluginData};
use hyper::header::Cookie as CookieHeader;
use hyper::header::SetCookie;
use cookie::Cookie;
use textnonce::TextNonce;
header! { (Dnt, "Dnt") => [String] }
header! { (Tk, "Tk") => [String] }
pub struct Session {
cookie_name: String,
secure: bool,
http_only: bool,
respect_dnt_ad_absurdum: bool,
}
impl Session
{
pub fn new(cookie_name: String, secure: bool, http_only: bool) -> Session {
Session {
cookie_name: cookie_name,
secure: secure,
http_only: http_only,
respect_dnt_ad_absurdum: false,
}
}
pub fn respect_dnt_ad_absurdum(&mut self) {
self.respect_dnt_ad_absurdum = true;
}
}
impl<S,E> Plugin<S,E> for Session
where S: 'static, E: 'static
{
fn handle(&self, mut data: PluginData<S>)
-> Box<Future<Item = PluginData<S>, Error = E>>
{
if self.respect_dnt_ad_absurdum {
let mut dnt = false;
if let Some(header) = data.request.headers().get::<Dnt>() {
match *header {
Dnt(ref s) => {
if &*s != "0" {
dnt = true;
}
},
}
}
if dnt {
data.session_id = None;
data.response.headers_mut().set(Tk("N".to_owned()));
return Box::new(::futures::future::ok(data));
}
}
let mut maybe_key: Option<String> = None;
if let Some(cookie_header) = data.request.headers().get::<CookieHeader>() {
if let Some(cookie_value) = cookie_header.get(&*self.cookie_name) {
maybe_key = Some(cookie_value.to_owned());
}
}
if let Some(key) = maybe_key {
data.session_id = Some(key.to_owned());
return Box::new(::futures::future::ok(data));
}
let key = TextNonce::new().into_string();
data.session_id = Some(key.clone());
let mut cookie = Cookie::new(self.cookie_name.clone(), key);
cookie.set_path("/"); cookie.set_secure(self.secure);
cookie.set_http_only(self.http_only);
data.response.headers_mut().set(
SetCookie(vec![ cookie.to_string() ]));
Box::new(::futures::future::ok(data))
}
}