1
- use async_session:: { uuid:: Uuid , Session , SessionStore } ;
2
- use http_types:: cookies:: Cookie ;
3
- use redis:: AsyncCommands ;
4
- use redis:: { Client , RedisError } ;
1
+ use async_session:: { async_trait, base64, serde_json, utils, Session , SessionStore } ;
2
+ use redis:: { AsyncCommands , Client , RedisError } ;
5
3
use std:: time:: Duration ;
6
4
7
- #[ derive( Clone ) ]
5
+ #[ derive( Clone , Debug ) ]
8
6
pub struct RedisSessionStore {
9
7
client : Client ,
10
8
ttl : Duration ,
9
+ prefix : Option < String > ,
11
10
}
12
11
13
12
impl RedisSessionStore {
14
13
pub fn from_client ( client : Client ) -> Self {
15
14
Self {
16
15
client,
17
16
ttl : Duration :: from_secs ( 86400 ) ,
17
+ prefix : None ,
18
18
}
19
19
}
20
20
21
21
pub fn new ( connection_info : impl redis:: IntoConnectionInfo ) -> Result < Self , RedisError > {
22
22
Ok ( Self :: from_client ( Client :: open ( connection_info) ?) )
23
23
}
24
+
25
+ pub fn with_prefix ( mut self , prefix : String ) -> Self {
26
+ self . prefix = Some ( prefix) ;
27
+ self
28
+ }
29
+
30
+ pub fn with_ttl ( mut self , ttl : Duration ) -> Self {
31
+ self . ttl = ttl;
32
+ self
33
+ }
34
+
35
+ fn prefix_key ( & self , key : impl AsRef < str > ) -> String {
36
+ if let Some ( ref prefix) = self . prefix {
37
+ format ! ( "{}{}" , prefix, key. as_ref( ) )
38
+ } else {
39
+ key. as_ref ( ) . into ( )
40
+ }
41
+ }
42
+
43
+ async fn connection ( & self ) -> redis:: RedisResult < redis:: aio:: Connection > {
44
+ self . client . get_async_std_connection ( ) . await
45
+ }
24
46
}
25
47
26
- #[ async_trait:: async_trait ]
48
+ #[ async_trait]
27
49
impl SessionStore for RedisSessionStore {
28
50
type Error = Error ;
29
51
30
- async fn load_session ( & self , cookie : Cookie < ' _ > ) -> Result < Option < Session > , Self :: Error > {
31
- let mut connection = self . client . get_async_std_connection ( ) . await ?;
32
- let value: String = connection. get ( cookie. value ( ) ) . await ?;
33
- let session: Session = serde_json:: from_str ( & value) ?;
34
- Ok ( Some ( session) )
52
+ async fn load_session ( & self , cookie_value : String ) -> Option < Session > {
53
+ let id = utils:: id_from_string ( & cookie_value) . ok ( ) ?;
54
+ let mut connection = self . connection ( ) . await . ok ( ) ?;
55
+ match connection. get :: < _ , Option < String > > ( id) . await . ok ( ) ? {
56
+ Some ( value) => serde_json:: from_str ( & value) . ok ( ) ?,
57
+ None => None ,
58
+ }
35
59
}
36
60
37
- async fn store_session ( & self , session : Session ) -> Result < String , Self :: Error > {
61
+ async fn store_session ( & self , mut session : Session ) -> Option < String > {
38
62
let id = session. id ( ) ;
39
- let mut connection = self . client . get_async_std_connection ( ) . await ?;
40
- let string = serde_json:: to_string ( & session) ?;
63
+ let string = serde_json:: to_string ( & session) . ok ( ) ?;
41
64
42
- let _: ( ) = connection
43
- . set_ex ( & id, string, self . ttl . as_secs ( ) as usize )
44
- . await ?;
65
+ let mut connection = self . connection ( ) . await . ok ( ) ?;
66
+ connection
67
+ . set_ex :: < _ , _ , ( ) > ( id, string, self . ttl . as_secs ( ) as usize )
68
+ . await
69
+ . ok ( ) ?;
70
+
71
+ session. take_cookie_value ( )
72
+ }
45
73
46
- Ok ( id)
74
+ async fn destroy_session ( & self , session : Session ) -> Result < ( ) , Self :: Error > {
75
+ self . connection ( )
76
+ . await ?
77
+ . del :: < _ , ( ) > ( self . prefix_key ( session. id ( ) . to_string ( ) ) )
78
+ . await ?;
79
+ Ok ( ( ) )
47
80
}
48
81
49
- async fn create_session ( & self ) -> Result < Session , Self :: Error > {
50
- let sess = Session :: new ( ) ;
51
- sess. insert ( "id" . to_string ( ) , Uuid :: new_v4 ( ) . to_string ( ) ) ;
52
- Ok ( sess)
82
+ async fn clear_store ( & self ) -> Result < ( ) , Self :: Error > {
83
+ self . connection ( ) . await ?. del ( self . prefix_key ( "*" ) ) . await ?;
84
+ Ok ( ( ) )
53
85
}
54
86
}
55
87
56
88
#[ derive( Debug ) ]
57
89
pub enum Error {
58
90
RedisError ( RedisError ) ,
59
91
SerdeError ( serde_json:: Error ) ,
92
+ Base64Error ( base64:: DecodeError ) ,
60
93
}
61
94
62
95
impl std:: fmt:: Display for Error {
63
96
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
64
97
match self {
65
98
Error :: RedisError ( e) => e. fmt ( f) ,
66
99
Error :: SerdeError ( e) => e. fmt ( f) ,
100
+ Error :: Base64Error ( e) => e. fmt ( f) ,
67
101
}
68
102
}
69
103
}
@@ -74,6 +108,12 @@ impl From<serde_json::Error> for Error {
74
108
}
75
109
}
76
110
111
+ impl From < base64:: DecodeError > for Error {
112
+ fn from ( e : base64:: DecodeError ) -> Self {
113
+ Self :: Base64Error ( e)
114
+ }
115
+ }
116
+
77
117
impl From < RedisError > for Error {
78
118
fn from ( e : RedisError ) -> Self {
79
119
Self :: RedisError ( e)
0 commit comments