mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
refactor session impl
This commit is contained in:
parent
d9a4fadaae
commit
9b6343d54b
@ -63,6 +63,7 @@
|
|||||||
//! let _ = sys.run();
|
//! let _ = sys.run();
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -72,7 +73,8 @@ use cookie::{Cookie, CookieJar, Key};
|
|||||||
use futures::future::{err as FutErr, ok as FutOk, FutureResult};
|
use futures::future::{err as FutErr, ok as FutOk, FutureResult};
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use http::header::{self, HeaderValue};
|
use http::header::{self, HeaderValue};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::error::Error as JsonError;
|
use serde_json::error::Error as JsonError;
|
||||||
use time::Duration;
|
use time::Duration;
|
||||||
@ -101,17 +103,15 @@ use middleware::{Middleware, Response, Started};
|
|||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
pub trait RequestSession {
|
pub trait RequestSession {
|
||||||
fn session(&mut self) -> Session;
|
fn session(&self) -> Session;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> RequestSession for HttpRequest<S> {
|
impl<S> RequestSession for HttpRequest<S> {
|
||||||
fn session(&mut self) -> Session {
|
fn session(&self) -> Session {
|
||||||
if let Some(s_impl) = self.extensions_mut().get_mut::<Arc<SessionImplBox>>() {
|
if let Some(s_impl) = self.extensions().get::<Arc<SessionImplCell>>() {
|
||||||
if let Some(s) = Arc::get_mut(s_impl) {
|
return Session(SessionInner::Session(Arc::clone(&s_impl)));
|
||||||
return Session(s.0.as_mut());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Session(unsafe { &mut DUMMY })
|
Session(SessionInner::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,41 +137,65 @@ impl<S> RequestSession for HttpRequest<S> {
|
|||||||
/// }
|
/// }
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Session<'a>(&'a mut SessionImpl);
|
pub struct Session(SessionInner);
|
||||||
|
|
||||||
impl<'a> Session<'a> {
|
enum SessionInner {
|
||||||
|
Session(Arc<SessionImplCell>),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Session {
|
||||||
/// Get a `value` from the session.
|
/// Get a `value` from the session.
|
||||||
pub fn get<T: Deserialize<'a>>(&'a self, key: &str) -> Result<Option<T>> {
|
pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>> {
|
||||||
if let Some(s) = self.0.get(key) {
|
match self.0 {
|
||||||
Ok(Some(serde_json::from_str(s)?))
|
SessionInner::Session(ref sess) => {
|
||||||
} else {
|
if let Some(s) = sess.as_ref().0.borrow().get(key) {
|
||||||
Ok(None)
|
Ok(Some(serde_json::from_str(s)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SessionInner::None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a `value` from the session.
|
/// Set a `value` from the session.
|
||||||
pub fn set<T: Serialize>(&mut self, key: &str, value: T) -> Result<()> {
|
pub fn set<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
|
||||||
self.0.set(key, serde_json::to_string(&value)?);
|
match self.0 {
|
||||||
Ok(())
|
SessionInner::Session(ref sess) => {
|
||||||
|
sess.as_ref()
|
||||||
|
.0
|
||||||
|
.borrow_mut()
|
||||||
|
.set(key, serde_json::to_string(&value)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
SessionInner::None => Ok(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove value from the session.
|
/// Remove value from the session.
|
||||||
pub fn remove(&'a mut self, key: &str) {
|
pub fn remove(&self, key: &str) {
|
||||||
self.0.remove(key)
|
match self.0 {
|
||||||
|
SessionInner::Session(ref sess) => sess.as_ref().0.borrow_mut().remove(key),
|
||||||
|
SessionInner::None => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the session.
|
/// Clear the session.
|
||||||
pub fn clear(&'a mut self) {
|
pub fn clear(&self) {
|
||||||
self.0.clear()
|
match self.0 {
|
||||||
|
SessionInner::Session(ref sess) => sess.as_ref().0.borrow_mut().clear(),
|
||||||
|
SessionInner::None => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SessionImplBox(Box<SessionImpl>);
|
struct SessionImplCell(RefCell<Box<SessionImpl>>);
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
unsafe impl Send for SessionImplBox {}
|
unsafe impl Send for SessionImplCell {}
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
unsafe impl Sync for SessionImplBox {}
|
unsafe impl Sync for SessionImplCell {}
|
||||||
|
|
||||||
/// Session storage middleware
|
/// Session storage middleware
|
||||||
///
|
///
|
||||||
@ -206,8 +230,9 @@ impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
|
|||||||
.from_request(&mut req)
|
.from_request(&mut req)
|
||||||
.then(move |res| match res {
|
.then(move |res| match res {
|
||||||
Ok(sess) => {
|
Ok(sess) => {
|
||||||
req.extensions_mut()
|
req.extensions_mut().insert(Arc::new(SessionImplCell(
|
||||||
.insert(Arc::new(SessionImplBox(Box::new(sess))));
|
RefCell::new(Box::new(sess)),
|
||||||
|
)));
|
||||||
FutOk(None)
|
FutOk(None)
|
||||||
}
|
}
|
||||||
Err(err) => FutErr(err),
|
Err(err) => FutErr(err),
|
||||||
@ -218,8 +243,8 @@ impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
|
|||||||
fn response(
|
fn response(
|
||||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||||
) -> Result<Response> {
|
) -> Result<Response> {
|
||||||
if let Some(s_box) = req.extensions_mut().remove::<Arc<SessionImplBox>>() {
|
if let Some(s_box) = req.extensions_mut().remove::<Arc<SessionImplCell>>() {
|
||||||
s_box.0.write(resp)
|
s_box.0.borrow_mut().write(resp)
|
||||||
} else {
|
} else {
|
||||||
Ok(Response::Done(resp))
|
Ok(Response::Done(resp))
|
||||||
}
|
}
|
||||||
@ -251,23 +276,6 @@ pub trait SessionBackend<S>: Sized + 'static {
|
|||||||
fn from_request(&self, request: &mut HttpRequest<S>) -> Self::ReadFuture;
|
fn from_request(&self, request: &mut HttpRequest<S>) -> Self::ReadFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dummy session impl, does not do anything
|
|
||||||
struct DummySessionImpl;
|
|
||||||
|
|
||||||
static mut DUMMY: DummySessionImpl = DummySessionImpl;
|
|
||||||
|
|
||||||
impl SessionImpl for DummySessionImpl {
|
|
||||||
fn get(&self, _: &str) -> Option<&str> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn set(&mut self, _: &str, _: String) {}
|
|
||||||
fn remove(&mut self, _: &str) {}
|
|
||||||
fn clear(&mut self) {}
|
|
||||||
fn write(&self, resp: HttpResponse) -> Result<Response> {
|
|
||||||
Ok(Response::Done(resp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Session that uses signed cookies as session storage
|
/// Session that uses signed cookies as session storage
|
||||||
pub struct CookieSession {
|
pub struct CookieSession {
|
||||||
changed: bool,
|
changed: bool,
|
||||||
|
Loading…
Reference in New Issue
Block a user