1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00
This commit is contained in:
Nikolay Kim 2018-07-20 14:58:14 -07:00
commit 31de5a1d24
5 changed files with 67 additions and 8 deletions

View File

@ -2,6 +2,8 @@
## 0.5.0 (2018-07-21) ## 0.5.0 (2018-07-21)
* Session cookie configuration
* Actix/Actix-web 0.7 compatibility * Actix/Actix-web 0.7 compatibility

View File

@ -37,6 +37,7 @@ tokio-io = "0.1"
tokio-codec = "0.1" tokio-codec = "0.1"
tokio-tcp = "0.1" tokio-tcp = "0.1"
redis-async = "0.3.2" redis-async = "0.3.2"
time = "0.1"
# actix web session # actix web session
actix-web = { git = "https://github.com/actix/actix-web.git", optional=true } actix-web = { git = "https://github.com/actix/actix-web.git", optional=true }

View File

@ -19,6 +19,7 @@ extern crate log;
extern crate redis_async; extern crate redis_async;
#[macro_use] #[macro_use]
extern crate failure; extern crate failure;
extern crate time;
mod redis; mod redis;
pub use redis::{Command, RedisActor}; pub use redis::{Command, RedisActor};

View File

@ -37,10 +37,13 @@ impl RedisActor {
pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> { pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> {
let addr = addr.into(); let addr = addr.into();
let mut backoff = ExponentialBackoff::default();
backoff.max_elapsed_time = None;
Supervisor::start(|_| RedisActor { Supervisor::start(|_| RedisActor {
addr, addr,
cell: None, cell: None,
backoff: ExponentialBackoff::default(), backoff: backoff,
queue: VecDeque::new(), queue: VecDeque::new(),
}) })
} }
@ -74,8 +77,6 @@ impl Actor for RedisActor {
// we stop current context, supervisor will restart it. // we stop current context, supervisor will restart it.
if let Some(timeout) = act.backoff.next_backoff() { if let Some(timeout) = act.backoff.next_backoff() {
ctx.run_later(timeout, |_, ctx| ctx.stop()); ctx.run_later(timeout, |_, ctx| ctx.stop());
} else {
ctx.stop();
} }
} }
}) })
@ -85,8 +86,6 @@ impl Actor for RedisActor {
// we stop current context, supervisor will restart it. // we stop current context, supervisor will restart it.
if let Some(timeout) = act.backoff.next_backoff() { if let Some(timeout) = act.backoff.next_backoff() {
ctx.run_later(timeout, |_, ctx| ctx.stop()); ctx.run_later(timeout, |_, ctx| ctx.stop());
} else {
ctx.stop();
} }
}) })
.wait(ctx); .wait(ctx);

View File

@ -6,7 +6,7 @@ use actix::prelude::*;
use actix_web::middleware::session::{SessionBackend, SessionImpl}; use actix_web::middleware::session::{SessionBackend, SessionImpl};
use actix_web::middleware::Response as MiddlewareResponse; use actix_web::middleware::Response as MiddlewareResponse;
use actix_web::{error, Error, HttpRequest, HttpResponse, Result}; use actix_web::{error, Error, HttpRequest, HttpResponse, Result};
use cookie::{Cookie, CookieJar, Key}; use cookie::{Cookie, CookieJar, Key, SameSite};
use futures::future::{err as FutErr, ok as FutOk, Either}; use futures::future::{err as FutErr, ok as FutOk, Either};
use futures::Future; use futures::Future;
use http::header::{self, HeaderValue}; use http::header::{self, HeaderValue};
@ -14,6 +14,7 @@ use rand::distributions::Alphanumeric;
use rand::{self, Rng}; use rand::{self, Rng};
use redis_async::resp::RespValue; use redis_async::resp::RespValue;
use serde_json; use serde_json;
use time::Duration;
use redis::{Command, RedisActor}; use redis::{Command, RedisActor};
@ -80,6 +81,11 @@ impl RedisSessionBackend {
ttl: "7200".to_owned(), ttl: "7200".to_owned(),
addr: RedisActor::start(addr), addr: RedisActor::start(addr),
name: "actix-session".to_owned(), name: "actix-session".to_owned(),
path: "/".to_owned(),
domain: None,
secure: false,
max_age: Some(Duration::days(7)),
same_site: None,
})) }))
} }
@ -94,6 +100,38 @@ impl RedisSessionBackend {
Rc::get_mut(&mut self.0).unwrap().name = name.to_owned(); Rc::get_mut(&mut self.0).unwrap().name = name.to_owned();
self self
} }
/// Set custom cookie path
pub fn cookie_path(mut self, path: &str) -> Self {
Rc::get_mut(&mut self.0).unwrap().path = path.to_owned();
self
}
/// Set custom cookie domain
pub fn cookie_domain(mut self, domain: &str) -> Self {
Rc::get_mut(&mut self.0).unwrap().domain = Some(domain.to_owned());
self
}
/// Set custom cookie secure
/// If the `secure` field is set, a cookie will only be transmitted when the
/// connection is secure - i.e. `https`
pub fn cookie_secure(mut self, secure: bool) -> Self {
Rc::get_mut(&mut self.0).unwrap().secure = secure;
self
}
/// Set custom cookie max-age
pub fn cookie_max_age(mut self, max_age: Duration) -> Self {
Rc::get_mut(&mut self.0).unwrap().max_age = Some(max_age);
self
}
/// Set custom cookie SameSite
pub fn cookie_same_site(mut self, same_site: SameSite) -> Self {
Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site);
self
}
} }
impl<S> SessionBackend<S> for RedisSessionBackend { impl<S> SessionBackend<S> for RedisSessionBackend {
@ -126,8 +164,13 @@ impl<S> SessionBackend<S> for RedisSessionBackend {
struct Inner { struct Inner {
key: Key, key: Key,
ttl: String, ttl: String,
name: String,
addr: Addr<RedisActor>, addr: Addr<RedisActor>,
name: String,
path: String,
domain: Option<String>,
secure: bool,
max_age: Option<Duration>,
same_site: Option<SameSite>,
} }
impl Inner { impl Inner {
@ -200,9 +243,22 @@ impl Inner {
.collect(); .collect();
let mut cookie = Cookie::new(self.name.clone(), value.clone()); let mut cookie = Cookie::new(self.name.clone(), value.clone());
cookie.set_path("/"); cookie.set_path(self.path.clone());
cookie.set_secure(self.secure);
cookie.set_http_only(true); cookie.set_http_only(true);
if let Some(ref domain) = self.domain {
cookie.set_domain(domain.clone());
}
if let Some(max_age) = self.max_age {
cookie.set_max_age(max_age);
}
if let Some(same_site) = self.same_site {
cookie.set_same_site(same_site);
}
// set cookie // set cookie
let mut jar = CookieJar::new(); let mut jar = CookieJar::new();
jar.signed(&self.key).add(cookie); jar.signed(&self.key).add(cookie);