2021-03-21 10:38:29 +01:00
|
|
|
//! Sessions for Actix Web.
|
2019-03-05 19:12:49 +01:00
|
|
|
//!
|
2021-03-21 10:38:29 +01:00
|
|
|
//! Provides a general solution for session management. Session middleware could provide different
|
|
|
|
//! implementations which could be accessed via general session API.
|
2019-03-05 19:12:49 +01:00
|
|
|
//!
|
2021-03-21 10:38:29 +01:00
|
|
|
//! This crate provides a general solution for session management and includes a cookie backend.
|
|
|
|
//! Other backend implementations can be built to use persistent or key-value stores, for example.
|
2019-03-05 19:12:49 +01:00
|
|
|
//!
|
2021-03-21 10:38:29 +01:00
|
|
|
//! In general, some session middleware, such as a [`CookieSession`] is initialized and applied.
|
|
|
|
//! To access session data, the [`Session`] extractor must be used. This extractor allows reading
|
|
|
|
//! modifying session data.
|
2019-03-05 19:12:49 +01:00
|
|
|
//!
|
2021-03-21 10:38:29 +01:00
|
|
|
//! ```no_run
|
2019-03-07 00:47:15 +01:00
|
|
|
//! use actix_web::{web, App, HttpServer, HttpResponse, Error};
|
2019-03-06 03:47:18 +01:00
|
|
|
//! use actix_session::{Session, CookieSession};
|
2019-03-05 19:12:49 +01:00
|
|
|
//!
|
2019-03-06 03:47:18 +01:00
|
|
|
//! fn index(session: Session) -> Result<&'static str, Error> {
|
2019-03-05 19:12:49 +01:00
|
|
|
//! // access session data
|
2019-03-06 03:47:18 +01:00
|
|
|
//! if let Some(count) = session.get::<i32>("counter")? {
|
2019-03-05 19:12:49 +01:00
|
|
|
//! println!("SESSION value: {}", count);
|
2021-03-23 23:35:27 +01:00
|
|
|
//! session.insert("counter", count + 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
//! } else {
|
2021-03-23 23:35:27 +01:00
|
|
|
//! session.insert("counter", 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! Ok("Welcome!")
|
|
|
|
//! }
|
|
|
|
//!
|
2019-12-08 07:31:16 +01:00
|
|
|
//! #[actix_rt::main]
|
|
|
|
//! async fn main() -> std::io::Result<()> {
|
2019-03-06 03:47:18 +01:00
|
|
|
//! HttpServer::new(
|
2021-03-21 10:38:29 +01:00
|
|
|
//! || App::new()
|
|
|
|
//! // create cookie based session middleware
|
|
|
|
//! .wrap(CookieSession::signed(&[0; 32]).secure(false))
|
|
|
|
//! .default_service(web::to(|| HttpResponse::Ok())))
|
|
|
|
//! .bind(("127.0.0.1", 8080))?
|
2019-12-22 14:12:22 +01:00
|
|
|
//! .run()
|
2019-12-08 07:31:16 +01:00
|
|
|
//! .await
|
2019-03-05 19:12:49 +01:00
|
|
|
//! }
|
|
|
|
//! ```
|
2020-09-11 17:26:15 +02:00
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
|
|
#![warn(missing_docs)]
|
2020-09-11 17:26:15 +02:00
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
use std::{
|
|
|
|
cell::{Ref, RefCell},
|
|
|
|
collections::HashMap,
|
|
|
|
mem,
|
|
|
|
rc::Rc,
|
|
|
|
};
|
2019-03-05 19:12:49 +01:00
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
use actix_web::{
|
|
|
|
dev::{Extensions, Payload, RequestHead, ServiceRequest, ServiceResponse},
|
|
|
|
Error, FromRequest, HttpMessage, HttpRequest,
|
2019-12-06 06:21:43 +01:00
|
|
|
};
|
2020-03-14 22:58:47 +01:00
|
|
|
use futures_util::future::{ok, Ready};
|
2021-03-21 10:38:29 +01:00
|
|
|
use serde::{de::DeserializeOwned, Serialize};
|
2019-03-05 19:12:49 +01:00
|
|
|
|
2019-06-03 06:30:30 +02:00
|
|
|
#[cfg(feature = "cookie-session")]
|
2019-03-06 03:47:18 +01:00
|
|
|
mod cookie;
|
2019-06-03 06:30:30 +02:00
|
|
|
#[cfg(feature = "cookie-session")]
|
2021-03-23 23:35:27 +01:00
|
|
|
pub use self::cookie::CookieSession;
|
2019-03-05 19:12:49 +01:00
|
|
|
|
|
|
|
/// The high-level interface you use to modify session data.
|
|
|
|
///
|
2021-03-21 10:38:29 +01:00
|
|
|
/// Session object is obtained with [`UserSession::get_session`]. The [`UserSession`] trait is
|
|
|
|
/// implemented for `HttpRequest`, `ServiceRequest`, and `RequestHead`.
|
2019-03-05 19:12:49 +01:00
|
|
|
///
|
2021-03-21 10:38:29 +01:00
|
|
|
/// ```
|
2019-03-06 03:47:18 +01:00
|
|
|
/// use actix_session::Session;
|
2021-03-21 10:38:29 +01:00
|
|
|
/// use actix_web::Result;
|
2019-03-05 19:12:49 +01:00
|
|
|
///
|
2021-03-21 10:38:29 +01:00
|
|
|
/// async fn index(session: Session) -> Result<&'static str> {
|
2019-03-05 19:12:49 +01:00
|
|
|
/// // access session data
|
2019-03-06 03:47:18 +01:00
|
|
|
/// if let Some(count) = session.get::<i32>("counter")? {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// session.insert("counter", count + 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
/// } else {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// session.insert("counter", 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// Ok("Welcome!")
|
|
|
|
/// }
|
|
|
|
/// ```
|
2019-03-06 03:47:18 +01:00
|
|
|
pub struct Session(Rc<RefCell<SessionInner>>);
|
2019-03-05 19:12:49 +01:00
|
|
|
|
2021-03-21 10:38:29 +01:00
|
|
|
/// Extraction of a [`Session`] object.
|
2019-04-28 18:08:51 +02:00
|
|
|
pub trait UserSession {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Extract the [`Session`] object
|
2019-12-20 08:59:07 +01:00
|
|
|
fn get_session(&self) -> Session;
|
2019-04-28 18:08:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession for HttpRequest {
|
2019-12-20 08:59:07 +01:00
|
|
|
fn get_session(&self) -> Session {
|
2019-04-28 18:08:51 +02:00
|
|
|
Session::get_session(&mut *self.extensions_mut())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UserSession for ServiceRequest {
|
2019-12-20 08:59:07 +01:00
|
|
|
fn get_session(&self) -> Session {
|
2019-04-28 18:08:51 +02:00
|
|
|
Session::get_session(&mut *self.extensions_mut())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 06:21:43 +01:00
|
|
|
impl UserSession for RequestHead {
|
2019-12-20 08:59:07 +01:00
|
|
|
fn get_session(&self) -> Session {
|
2019-12-06 06:21:43 +01:00
|
|
|
Session::get_session(&mut *self.extensions_mut())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Status of a [`Session`].
|
2019-06-12 14:03:27 +02:00
|
|
|
#[derive(PartialEq, Clone, Debug)]
|
|
|
|
pub enum SessionStatus {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Session has been updated and requires a new persist operation.
|
2019-06-12 14:03:27 +02:00
|
|
|
Changed,
|
2021-03-23 23:35:27 +01:00
|
|
|
|
|
|
|
/// Session is flagged for deletion and should be removed from client and server.
|
|
|
|
///
|
|
|
|
/// Most operations on the session after purge flag is set should have no effect.
|
2019-06-12 14:03:27 +02:00
|
|
|
Purged,
|
2021-03-23 23:35:27 +01:00
|
|
|
|
|
|
|
/// Session is flagged for refresh.
|
|
|
|
///
|
|
|
|
/// For example, when using a backend that has a TTL (time-to-live) expiry on the session entry,
|
|
|
|
/// the session will be refreshed even if no data inside it has changed. The client may also
|
|
|
|
/// be notified of the refresh.
|
2019-06-12 14:03:27 +02:00
|
|
|
Renewed,
|
2021-03-23 23:35:27 +01:00
|
|
|
|
|
|
|
/// Session is unchanged from when last seen (if exists).
|
|
|
|
///
|
|
|
|
/// This state also captures new (previously unissued) sessions such as a user's first
|
|
|
|
/// site visit.
|
2019-07-08 19:25:51 +02:00
|
|
|
Unchanged,
|
2019-06-12 14:03:27 +02:00
|
|
|
}
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-06-12 14:03:27 +02:00
|
|
|
impl Default for SessionStatus {
|
|
|
|
fn default() -> SessionStatus {
|
|
|
|
SessionStatus::Unchanged
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-06 03:47:18 +01:00
|
|
|
#[derive(Default)]
|
|
|
|
struct SessionInner {
|
|
|
|
state: HashMap<String, String>,
|
2021-03-23 23:35:27 +01:00
|
|
|
status: SessionStatus,
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Session {
|
|
|
|
/// Get a `value` from the session.
|
2019-03-06 03:47:18 +01:00
|
|
|
pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>, Error> {
|
|
|
|
if let Some(s) = self.0.borrow().state.get(key) {
|
|
|
|
Ok(Some(serde_json::from_str(s)?))
|
|
|
|
} else {
|
|
|
|
Ok(None)
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Get all raw key-value data from the session.
|
|
|
|
///
|
|
|
|
/// Note that values are JSON encoded.
|
|
|
|
pub fn entries(&self) -> Ref<'_, HashMap<String, String>> {
|
|
|
|
Ref::map(self.0.borrow(), |inner| &inner.state)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Inserts a key-value pair into the session.
|
|
|
|
///
|
|
|
|
/// Any serializable value can be used and will be encoded as JSON in session data, hence why
|
|
|
|
/// only a reference to the value is taken.
|
|
|
|
pub fn insert(
|
|
|
|
&self,
|
|
|
|
key: impl Into<String>,
|
|
|
|
value: impl Serialize,
|
|
|
|
) -> Result<(), Error> {
|
2019-03-06 03:47:18 +01:00
|
|
|
let mut inner = self.0.borrow_mut();
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-06-12 16:11:38 +02:00
|
|
|
if inner.status != SessionStatus::Purged {
|
|
|
|
inner.status = SessionStatus::Changed;
|
2021-03-23 23:35:27 +01:00
|
|
|
let val = serde_json::to_string(&value)?;
|
|
|
|
inner.state.insert(key.into(), val);
|
2019-06-12 16:11:38 +02:00
|
|
|
}
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-03-06 03:47:18 +01:00
|
|
|
Ok(())
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove value from the session.
|
2021-03-23 23:35:27 +01:00
|
|
|
///
|
|
|
|
/// If present, the JSON encoded value is returned.
|
|
|
|
pub fn remove(&self, key: &str) -> Option<String> {
|
2019-03-06 03:47:18 +01:00
|
|
|
let mut inner = self.0.borrow_mut();
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-06-12 16:11:38 +02:00
|
|
|
if inner.status != SessionStatus::Purged {
|
|
|
|
inner.status = SessionStatus::Changed;
|
2021-03-23 23:35:27 +01:00
|
|
|
return inner.state.remove(key);
|
2019-06-12 16:11:38 +02:00
|
|
|
}
|
2021-03-23 23:35:27 +01:00
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove value from the session and deserialize.
|
|
|
|
///
|
|
|
|
/// Returns None if key was not present in session. Returns T if deserialization succeeds,
|
|
|
|
/// otherwise returns un-deserialized JSON string.
|
|
|
|
pub fn remove_as<T: DeserializeOwned>(
|
|
|
|
&self,
|
|
|
|
key: &str,
|
|
|
|
) -> Option<Result<T, String>> {
|
|
|
|
self.remove(key)
|
|
|
|
.map(|val_str| match serde_json::from_str(&val_str) {
|
|
|
|
Ok(val) => Ok(val),
|
|
|
|
Err(_err) => {
|
|
|
|
log::debug!(
|
|
|
|
"removed value (key: {}) could not be deserialized as {}",
|
|
|
|
key,
|
|
|
|
std::any::type_name::<T>()
|
|
|
|
);
|
|
|
|
Err(val_str)
|
|
|
|
}
|
|
|
|
})
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Clear the session.
|
|
|
|
pub fn clear(&self) {
|
2019-03-06 03:47:18 +01:00
|
|
|
let mut inner = self.0.borrow_mut();
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-06-12 16:11:38 +02:00
|
|
|
if inner.status != SessionStatus::Purged {
|
|
|
|
inner.status = SessionStatus::Changed;
|
|
|
|
inner.state.clear()
|
|
|
|
}
|
2019-03-06 03:47:18 +01:00
|
|
|
}
|
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Removes session both client and server side.
|
2019-06-12 14:03:27 +02:00
|
|
|
pub fn purge(&self) {
|
|
|
|
let mut inner = self.0.borrow_mut();
|
|
|
|
inner.status = SessionStatus::Purged;
|
|
|
|
inner.state.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Renews the session key, assigning existing session state to new key.
|
|
|
|
pub fn renew(&self) {
|
|
|
|
let mut inner = self.0.borrow_mut();
|
2021-03-23 23:35:27 +01:00
|
|
|
|
2019-06-12 16:11:38 +02:00
|
|
|
if inner.status != SessionStatus::Purged {
|
|
|
|
inner.status = SessionStatus::Renewed;
|
|
|
|
}
|
2019-06-12 14:03:27 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 18:49:58 +02:00
|
|
|
/// Adds the given key-value pairs to the session on the request.
|
|
|
|
///
|
|
|
|
/// Values that match keys already existing on the session will be overwritten. Values should
|
|
|
|
/// already be JSON serialized.
|
|
|
|
///
|
2021-03-21 10:38:29 +01:00
|
|
|
/// # Examples
|
2020-04-07 18:49:58 +02:00
|
|
|
/// ```
|
|
|
|
/// # use actix_session::Session;
|
|
|
|
/// # use actix_web::test;
|
|
|
|
/// let mut req = test::TestRequest::default().to_srv_request();
|
|
|
|
///
|
|
|
|
/// Session::set_session(
|
|
|
|
/// &mut req,
|
2021-03-23 23:35:27 +01:00
|
|
|
/// vec![("counter".to_string(), serde_json::to_string(&0).unwrap())],
|
2020-04-07 18:49:58 +02:00
|
|
|
/// );
|
|
|
|
/// ```
|
2019-04-13 23:50:54 +02:00
|
|
|
pub fn set_session(
|
|
|
|
req: &mut ServiceRequest,
|
2021-03-23 23:35:27 +01:00
|
|
|
data: impl IntoIterator<Item = (String, String)>,
|
2019-03-06 03:47:18 +01:00
|
|
|
) {
|
2019-04-07 23:43:07 +02:00
|
|
|
let session = Session::get_session(&mut *req.extensions_mut());
|
2019-03-06 03:47:18 +01:00
|
|
|
let mut inner = session.0.borrow_mut();
|
|
|
|
inner.state.extend(data);
|
|
|
|
}
|
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
/// Returns session status and iterator of key-value pairs of changes.
|
2019-03-06 03:47:18 +01:00
|
|
|
pub fn get_changes<B>(
|
|
|
|
res: &mut ServiceResponse<B>,
|
2021-03-23 23:35:27 +01:00
|
|
|
) -> (SessionStatus, impl Iterator<Item = (String, String)>) {
|
2019-03-06 03:47:18 +01:00
|
|
|
if let Some(s_impl) = res
|
|
|
|
.request()
|
|
|
|
.extensions()
|
|
|
|
.get::<Rc<RefCell<SessionInner>>>()
|
|
|
|
{
|
2021-03-23 23:35:27 +01:00
|
|
|
let state = mem::take(&mut s_impl.borrow_mut().state);
|
|
|
|
(s_impl.borrow().status.clone(), state.into_iter())
|
2019-03-06 03:47:18 +01:00
|
|
|
} else {
|
2021-03-23 23:35:27 +01:00
|
|
|
(SessionStatus::Unchanged, HashMap::new().into_iter())
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
}
|
2019-03-06 03:47:18 +01:00
|
|
|
|
2019-06-13 15:19:03 +02:00
|
|
|
fn get_session(extensions: &mut Extensions) -> Session {
|
2019-04-07 23:43:07 +02:00
|
|
|
if let Some(s_impl) = extensions.get::<Rc<RefCell<SessionInner>>>() {
|
2021-08-31 00:10:36 +02:00
|
|
|
return Session(Rc::clone(s_impl));
|
2019-03-06 03:47:18 +01:00
|
|
|
}
|
|
|
|
let inner = Rc::new(RefCell::new(SessionInner::default()));
|
2019-04-07 23:43:07 +02:00
|
|
|
extensions.insert(inner.clone());
|
2019-03-06 03:47:18 +01:00
|
|
|
Session(inner)
|
|
|
|
}
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Extractor implementation for Session type.
|
|
|
|
///
|
2021-03-23 23:35:27 +01:00
|
|
|
/// # Examples
|
|
|
|
/// ```
|
2019-03-05 19:12:49 +01:00
|
|
|
/// # use actix_web::*;
|
2019-03-06 03:47:18 +01:00
|
|
|
/// use actix_session::Session;
|
2019-03-05 19:12:49 +01:00
|
|
|
///
|
2021-03-23 23:35:27 +01:00
|
|
|
/// #[get("/")]
|
|
|
|
/// async fn index(session: Session) -> Result<impl Responder> {
|
2019-03-05 19:12:49 +01:00
|
|
|
/// // access session data
|
|
|
|
/// if let Some(count) = session.get::<i32>("counter")? {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// session.insert("counter", count + 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
/// } else {
|
2021-03-23 23:35:27 +01:00
|
|
|
/// session.insert("counter", 1)?;
|
2019-03-05 19:12:49 +01:00
|
|
|
/// }
|
|
|
|
///
|
2021-03-23 23:35:27 +01:00
|
|
|
/// let count = session.get::<i32>("counter")?.unwrap();
|
|
|
|
/// Ok(format!("Counter: {}", count))
|
2019-03-05 19:12:49 +01:00
|
|
|
/// }
|
|
|
|
/// ```
|
2019-04-13 23:50:54 +02:00
|
|
|
impl FromRequest for Session {
|
2019-03-06 03:47:18 +01:00
|
|
|
type Error = Error;
|
2019-11-21 08:08:22 +01:00
|
|
|
type Future = Ready<Result<Session, Error>>;
|
2019-04-14 01:35:25 +02:00
|
|
|
type Config = ();
|
2019-03-05 19:12:49 +01:00
|
|
|
|
|
|
|
#[inline]
|
2019-04-13 23:50:54 +02:00
|
|
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
2019-11-21 08:08:22 +01:00
|
|
|
ok(Session::get_session(&mut *req.extensions_mut()))
|
2019-03-05 19:12:49 +01:00
|
|
|
}
|
|
|
|
}
|
2019-03-25 04:21:20 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use actix_web::{test, HttpResponse};
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn session() {
|
2019-04-03 00:00:10 +02:00
|
|
|
let mut req = test::TestRequest::default().to_srv_request();
|
2019-03-25 04:21:20 +01:00
|
|
|
|
|
|
|
Session::set_session(
|
|
|
|
&mut req,
|
2021-03-23 23:35:27 +01:00
|
|
|
vec![("key".to_string(), serde_json::to_string("value").unwrap())],
|
2019-03-25 04:21:20 +01:00
|
|
|
);
|
2019-04-07 23:43:07 +02:00
|
|
|
let session = Session::get_session(&mut *req.extensions_mut());
|
2019-03-25 04:21:20 +01:00
|
|
|
let res = session.get::<String>("key").unwrap();
|
|
|
|
assert_eq!(res, Some("value".to_string()));
|
|
|
|
|
2021-03-23 23:35:27 +01:00
|
|
|
session.insert("key2", "value2").unwrap();
|
2019-03-25 04:21:20 +01:00
|
|
|
session.remove("key");
|
|
|
|
|
|
|
|
let mut res = req.into_response(HttpResponse::Ok().finish());
|
2019-06-12 14:03:27 +02:00
|
|
|
let (_status, state) = Session::get_changes(&mut res);
|
2021-03-23 23:35:27 +01:00
|
|
|
let changes: Vec<_> = state.collect();
|
2019-03-25 04:21:20 +01:00
|
|
|
assert_eq!(changes, [("key2".to_string(), "\"value2\"".to_string())]);
|
|
|
|
}
|
2019-04-28 18:08:51 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn get_session() {
|
|
|
|
let mut req = test::TestRequest::default().to_srv_request();
|
|
|
|
|
|
|
|
Session::set_session(
|
|
|
|
&mut req,
|
2021-03-23 23:35:27 +01:00
|
|
|
vec![("key".to_string(), serde_json::to_string(&true).unwrap())],
|
2019-04-28 18:08:51 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
let session = req.get_session();
|
2020-04-07 18:49:58 +02:00
|
|
|
let res = session.get("key").unwrap();
|
|
|
|
assert_eq!(res, Some(true));
|
2019-04-28 18:08:51 +02:00
|
|
|
}
|
2019-06-12 14:03:27 +02:00
|
|
|
|
2019-12-06 06:21:43 +01:00
|
|
|
#[test]
|
|
|
|
fn get_session_from_request_head() {
|
|
|
|
let mut req = test::TestRequest::default().to_srv_request();
|
|
|
|
|
|
|
|
Session::set_session(
|
|
|
|
&mut req,
|
2021-03-23 23:35:27 +01:00
|
|
|
vec![("key".to_string(), serde_json::to_string(&10).unwrap())],
|
2019-12-06 06:21:43 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
let session = req.head_mut().get_session();
|
2020-04-07 18:49:58 +02:00
|
|
|
let res = session.get::<u32>("key").unwrap();
|
|
|
|
assert_eq!(res, Some(10));
|
2019-12-06 06:21:43 +01:00
|
|
|
}
|
|
|
|
|
2019-06-12 14:03:27 +02:00
|
|
|
#[test]
|
|
|
|
fn purge_session() {
|
2019-07-17 11:48:37 +02:00
|
|
|
let req = test::TestRequest::default().to_srv_request();
|
2019-06-12 14:03:27 +02:00
|
|
|
let session = Session::get_session(&mut *req.extensions_mut());
|
|
|
|
assert_eq!(session.0.borrow().status, SessionStatus::Unchanged);
|
|
|
|
session.purge();
|
|
|
|
assert_eq!(session.0.borrow().status, SessionStatus::Purged);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn renew_session() {
|
2019-07-17 11:48:37 +02:00
|
|
|
let req = test::TestRequest::default().to_srv_request();
|
2019-06-12 14:03:27 +02:00
|
|
|
let session = Session::get_session(&mut *req.extensions_mut());
|
|
|
|
assert_eq!(session.0.borrow().status, SessionStatus::Unchanged);
|
|
|
|
session.renew();
|
|
|
|
assert_eq!(session.0.borrow().status, SessionStatus::Renewed);
|
|
|
|
}
|
2021-03-23 23:35:27 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn session_entries() {
|
|
|
|
let session = Session(Rc::new(RefCell::new(SessionInner::default())));
|
|
|
|
session.insert("test_str", "val").unwrap();
|
|
|
|
session.insert("test_num", 1).unwrap();
|
|
|
|
|
|
|
|
let map = session.entries();
|
|
|
|
map.contains_key("test_str");
|
|
|
|
map.contains_key("test_num");
|
|
|
|
}
|
2019-03-25 04:21:20 +01:00
|
|
|
}
|