Files
gitks/session/storage/redis.rs
T
zhenyi 2bb5834167 feat(session): add session middleware with Redis storage support
- Implemented SessionMiddleware with cookie-based session key management
- Added support for encrypted and signed session cookies
- Integrated Redis backend for session state persistence
- Implemented session lifecycle management (create, update, delete)
- Added TTL extension policies for session timeout handling
- Created fluent builder for session middleware configuration
- Implemented cookie security features (secure, http-only, same-site)
- Added session state loading and persistence logic
- Implemented proper error handling and logging for session operations
- Added support for configurable session cookie parameters
- Implemented session key extraction and validation from requests
2026-06-07 17:42:27 +08:00

81 lines
2.4 KiB
Rust

use crate::cache::redis::AppRedis;
use crate::error::AppError;
use super::SessionKey;
use super::format::{deserialize_session_state, serialize_session_state};
use super::interface::{SessionState, SessionStore};
use super::utils::generate_session_key;
pub struct RedisSessionStore {
redis: AppRedis,
}
impl RedisSessionStore {
pub fn new(redis: AppRedis) -> Self {
Self { redis }
}
}
impl SessionStore for RedisSessionStore {
async fn load(&self, session_key: &SessionKey) -> Result<Option<SessionState>, AppError> {
let mut conn = self.redis.get_connection()?;
let value: Option<String> = redis::cmd("GET")
.arg(session_key.as_ref())
.query(&mut *conn.inner_mut())?;
match value {
None => Ok(None),
Some(v) => Ok(Some(deserialize_session_state(&v)?)),
}
}
async fn save(
&self,
session_state: SessionState,
ttl_secs: u64,
) -> Result<SessionKey, AppError> {
let body = serialize_session_state(&session_state)?;
let session_key = generate_session_key();
let mut conn = self.redis.get_connection()?;
redis::cmd("SETEX")
.arg(session_key.as_ref())
.arg(ttl_secs)
.arg(&body)
.query::<()>(&mut *conn.inner_mut())?;
Ok(session_key)
}
async fn update(
&self,
session_key: SessionKey,
session_state: SessionState,
ttl_secs: u64,
) -> Result<SessionKey, AppError> {
let body = serialize_session_state(&session_state)?;
let mut conn = self.redis.get_connection()?;
redis::cmd("SETEX")
.arg(session_key.as_ref())
.arg(ttl_secs)
.arg(&body)
.query::<()>(&mut *conn.inner_mut())?;
Ok(session_key)
}
async fn update_ttl(&self, session_key: &SessionKey, ttl_secs: u64) -> Result<(), AppError> {
let mut conn = self.redis.get_connection()?;
redis::cmd("EXPIRE")
.arg(session_key.as_ref())
.arg(ttl_secs)
.query::<()>(&mut *conn.inner_mut())?;
Ok(())
}
async fn delete(&self, session_key: &SessionKey) -> Result<(), AppError> {
let mut conn = self.redis.get_connection()?;
redis::cmd("DEL")
.arg(session_key.as_ref())
.query::<()>(&mut *conn.inner_mut())?;
Ok(())
}
}