actix_session/storage/
interface.rs

1use std::{collections::HashMap, future::Future};
2
3use actix_web::cookie::time::Duration;
4use derive_more::derive::Display;
5
6use super::SessionKey;
7
8pub(crate) type SessionState = HashMap<String, String>;
9
10/// The interface to retrieve and save the current session data from/to the chosen storage backend.
11///
12/// You can provide your own custom session store backend by implementing this trait.
13pub trait SessionStore {
14    /// Loads the session state associated to a session key.
15    fn load(
16        &self,
17        session_key: &SessionKey,
18    ) -> impl Future<Output = Result<Option<SessionState>, LoadError>>;
19
20    /// Persist the session state for a newly created session.
21    ///
22    /// Returns the corresponding session key.
23    fn save(
24        &self,
25        session_state: SessionState,
26        ttl: &Duration,
27    ) -> impl Future<Output = Result<SessionKey, SaveError>>;
28
29    /// Updates the session state associated to a pre-existing session key.
30    fn update(
31        &self,
32        session_key: SessionKey,
33        session_state: SessionState,
34        ttl: &Duration,
35    ) -> impl Future<Output = Result<SessionKey, UpdateError>>;
36
37    /// Updates the TTL of the session state associated to a pre-existing session key.
38    fn update_ttl(
39        &self,
40        session_key: &SessionKey,
41        ttl: &Duration,
42    ) -> impl Future<Output = Result<(), anyhow::Error>>;
43
44    /// Deletes a session from the store.
45    fn delete(&self, session_key: &SessionKey) -> impl Future<Output = Result<(), anyhow::Error>>;
46}
47
48// We cannot derive the `Error` implementation using `derive_more` for our custom errors:
49// `derive_more`'s `#[error(source)]` attribute requires the source implement the `Error` trait,
50// while it's actually enough for it to be able to produce a reference to a dyn Error.
51
52/// Possible failures modes for [`SessionStore::load`].
53#[derive(Debug, Display)]
54pub enum LoadError {
55    /// Failed to deserialize session state.
56    #[display("Failed to deserialize session state")]
57    Deserialization(anyhow::Error),
58
59    /// Something went wrong when retrieving the session state.
60    #[display("Something went wrong when retrieving the session state")]
61    Other(anyhow::Error),
62}
63
64impl std::error::Error for LoadError {
65    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
66        match self {
67            Self::Deserialization(err) => Some(err.as_ref()),
68            Self::Other(err) => Some(err.as_ref()),
69        }
70    }
71}
72
73/// Possible failures modes for [`SessionStore::save`].
74#[derive(Debug, Display)]
75pub enum SaveError {
76    /// Failed to serialize session state.
77    #[display("Failed to serialize session state")]
78    Serialization(anyhow::Error),
79
80    /// Something went wrong when persisting the session state.
81    #[display("Something went wrong when persisting the session state")]
82    Other(anyhow::Error),
83}
84
85impl std::error::Error for SaveError {
86    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
87        match self {
88            Self::Serialization(err) => Some(err.as_ref()),
89            Self::Other(err) => Some(err.as_ref()),
90        }
91    }
92}
93
94#[derive(Debug, Display)]
95/// Possible failures modes for [`SessionStore::update`].
96pub enum UpdateError {
97    /// Failed to serialize session state.
98    #[display("Failed to serialize session state")]
99    Serialization(anyhow::Error),
100
101    /// Something went wrong when updating the session state.
102    #[display("Something went wrong when updating the session state.")]
103    Other(anyhow::Error),
104}
105
106impl std::error::Error for UpdateError {
107    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
108        match self {
109            Self::Serialization(err) => Some(err.as_ref()),
110            Self::Other(err) => Some(err.as_ref()),
111        }
112    }
113}