async_session/
cookie_store.rs1use crate::{async_trait, Result, Session, SessionStore};
2
3#[derive(Debug, Clone, Copy)]
23pub struct CookieStore;
24
25impl CookieStore {
26 pub fn new() -> Self {
28 Self
29 }
30}
31
32#[async_trait]
33impl SessionStore for CookieStore {
34 async fn load_session(&self, cookie_value: String) -> Result<Option<Session>> {
35 let serialized = base64::decode(&cookie_value)?;
36 let session: Session = bincode::deserialize(&serialized)?;
37 Ok(session.validate())
38 }
39
40 async fn store_session(&self, session: Session) -> Result<Option<String>> {
41 let serialized = bincode::serialize(&session)?;
42 Ok(Some(base64::encode(serialized)))
43 }
44
45 async fn destroy_session(&self, _session: Session) -> Result {
46 Ok(())
47 }
48
49 async fn clear_store(&self) -> Result {
50 Ok(())
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use async_std::task;
58 use std::time::Duration;
59 #[async_std::test]
60 async fn creating_a_new_session_with_no_expiry() -> Result {
61 let store = CookieStore::new();
62 let mut session = Session::new();
63 session.insert("key", "Hello")?;
64 let cloned = session.clone();
65 let cookie_value = store.store_session(session).await?.unwrap();
66 let loaded_session = store.load_session(cookie_value).await?.unwrap();
67 assert_eq!(cloned.id(), loaded_session.id());
68 assert_eq!("Hello", &loaded_session.get::<String>("key").unwrap());
69 assert!(!loaded_session.is_expired());
70 assert!(loaded_session.validate().is_some());
71 Ok(())
72 }
73
74 #[async_std::test]
75 async fn updating_a_session() -> Result {
76 let store = CookieStore::new();
77 let mut session = Session::new();
78
79 session.insert("key", "value")?;
80 let cookie_value = store.store_session(session).await?.unwrap();
81
82 let mut session = store.load_session(cookie_value.clone()).await?.unwrap();
83 session.insert("key", "other value")?;
84
85 let new_cookie_value = store.store_session(session).await?.unwrap();
86 let session = store.load_session(new_cookie_value).await?.unwrap();
87 assert_eq!(&session.get::<String>("key").unwrap(), "other value");
88
89 Ok(())
90 }
91
92 #[async_std::test]
93 async fn updating_a_session_extending_expiry() -> Result {
94 let store = CookieStore::new();
95 let mut session = Session::new();
96 session.expire_in(Duration::from_secs(1));
97 let original_expires = session.expiry().unwrap().clone();
98 let cookie_value = store.store_session(session).await?.unwrap();
99
100 let mut session = store.load_session(cookie_value.clone()).await?.unwrap();
101
102 assert_eq!(session.expiry().unwrap(), &original_expires);
103 session.expire_in(Duration::from_secs(3));
104 let new_expires = session.expiry().unwrap().clone();
105 let cookie_value = store.store_session(session).await?.unwrap();
106
107 let session = store.load_session(cookie_value.clone()).await?.unwrap();
108 assert_eq!(session.expiry().unwrap(), &new_expires);
109
110 task::sleep(Duration::from_secs(3)).await;
111 assert_eq!(None, store.load_session(cookie_value).await?);
112
113 Ok(())
114 }
115
116 #[async_std::test]
117 async fn creating_a_new_session_with_expiry() -> Result {
118 let store = CookieStore::new();
119 let mut session = Session::new();
120 session.expire_in(Duration::from_secs(3));
121 session.insert("key", "value")?;
122 let cloned = session.clone();
123
124 let cookie_value = store.store_session(session).await?.unwrap();
125
126 let loaded_session = store.load_session(cookie_value.clone()).await?.unwrap();
127 assert_eq!(cloned.id(), loaded_session.id());
128 assert_eq!("value", &*loaded_session.get::<String>("key").unwrap());
129
130 assert!(!loaded_session.is_expired());
131
132 task::sleep(Duration::from_secs(3)).await;
133 assert_eq!(None, store.load_session(cookie_value).await?);
134
135 Ok(())
136 }
137}