Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede committed Aug 3, 2024
1 parent 307299d commit a8d77af
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 78 deletions.
5 changes: 1 addition & 4 deletions actix-session/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Add `redis-session-rustls` crate feature that enables `rustls`-secured Redis sessions.
- Add `redis-pool` crate feature (off-by-default) which enables `RedisSessionStore::{new, builder}_pooled()` consrtuctors.
- Rename `redis-rs-session` crate feature to `redis-session`.
- Rename `redis-rs-tls-session` crate feature to `redis-session-native-tls`.
- Remove `redis-actor-session` crate feature (and, therefore, the `actix-redis` based storage backend).
Expand All @@ -12,12 +13,8 @@
## 0.9.0

- Remove use of `async-trait` on `SessionStore` trait.
- Add `deadpool-redis` dependency; Implement `deadpool_redis::Pool` for `RedisSessionStore`. [#381]
- Update `actix-redis` dependency to `0.13`.
- Minimum supported Rust version (MSRV) is now 1.75.

[#381]: https://github.com/actix/actix-extras/pull/381

## 0.8.0

- Set secure attribute when adding a session removal cookie.
Expand Down
6 changes: 2 additions & 4 deletions actix-session/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ cookie-session = []
redis-session = ["dep:redis", "dep:rand"]
redis-session-native-tls = ["redis-session", "redis/tokio-native-tls-comp"]
redis-session-rustls = ["redis-session", "redis/tokio-rustls-comp"]
redis-dp-session = ["dep:deadpool-redis", "dep:rand"]
redis-pool = ["dep:deadpool-redis"]

[dependencies]
actix-service = "2"
Expand All @@ -39,9 +39,7 @@ tracing = { version = "0.1.30", default-features = false, features = ["log"] }

# redis-session
redis = { version = "0.26", default-features = false, features = ["tokio-comp", "connection-manager"], optional = true }

# redis-dp-session
deadpool-redis = { version = "0.14", optional = true }
deadpool-redis = { version = "0.15", optional = true }

[dev-dependencies]
actix-session = { path = ".", features = ["cookie-session", "redis-session"] }
Expand Down
13 changes: 7 additions & 6 deletions actix-session/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
#[cfg(feature = "cookie-session")]
mod cookie;
mod interface;
#[cfg(any(feature = "redis-session", feature = "redis-dp-session"))]
#[cfg(feature = "redis-session")]
mod redis_rs;
mod session_key;
#[cfg(any(feature = "redis-session", feature = "redis-dp-session"))]
#[cfg(feature = "redis-session")]
mod utils;

#[cfg(feature = "cookie-session")]
pub use self::cookie::CookieSessionStore;
#[cfg(any(feature = "redis-session", feature = "redis-dp-session"))]
pub use self::redis_rs::{RedisSessionStore, RedisSessionStoreBuilder};
#[cfg(any(feature = "redis-session", feature = "redis-dp-session"))]
pub use self::utils::generate_session_key;
pub use self::{
interface::{LoadError, SaveError, SessionStore, UpdateError},
session_key::SessionKey,
};
#[cfg(feature = "redis-session")]
pub use self::{
redis_rs::{RedisSessionStore, RedisSessionStoreBuilder},
utils::generate_session_key,
};
143 changes: 79 additions & 64 deletions actix-session/src/storage/redis_rs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use std::sync::Arc;

use actix_web::cookie::time::Duration;
use anyhow::Error;
#[cfg(not(feature = "redis-session"))]
use deadpool_redis::{redis, Pool};
#[cfg(feature = "redis-session")]
use redis::aio::ConnectionManager;
use redis::{AsyncCommands, Cmd, FromRedisValue, RedisResult, Value};
use redis::{
aio::ConnectionManager, AsyncCommands, Client, Cmd, FromRedisValue, RedisResult, Value,
};

use super::SessionKey;
use crate::storage::{
Expand Down Expand Up @@ -78,10 +76,17 @@ use crate::storage::{
#[derive(Clone)]
pub struct RedisSessionStore {
configuration: CacheConfiguration,
#[cfg(feature = "redis-session")]
client: ConnectionManager,
#[cfg(not(feature = "redis-session"))]
pool: Pool,
client: RedisSessionConn,
}

#[derive(Clone)]
enum RedisSessionConn {
/// Single connection.
Single(ConnectionManager),

/// Connection pool.
#[cfg(feature = "redis-pool")]
Pool(deadpool_redis::Pool),
}

#[derive(Clone)]
Expand All @@ -98,42 +103,44 @@ impl Default for CacheConfiguration {
}

impl RedisSessionStore {
/// A fluent API to configure [`RedisSessionStore`].
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`] - a
/// connection string for Redis.
#[cfg(feature = "redis-session")]
pub fn builder<S: Into<String>>(connection_string: S) -> RedisSessionStoreBuilder {
/// Returns a fluent API builder to configure [`RedisSessionStore`].
///
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`]
/// - a connection string for Redis.
pub fn builder(connection_string: impl Into<String>) -> RedisSessionStoreBuilder {
RedisSessionStoreBuilder {
configuration: CacheConfiguration::default(),
connection_string: connection_string.into(),
conn_builder: RedisSessionConnBuilder::Single(connection_string.into()),
}
}

/// A fluent API to configure [`RedisSessionStore`].
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`] - a
/// pool object for Redis.
#[cfg(not(feature = "redis-session"))]
pub fn builder<P: Into<Pool>>(pool: P) -> RedisSessionStoreBuilder {
/// Returns a fluent API builder to configure [`RedisSessionStore`].
///
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`]
/// - a pool object for Redis.
pub fn builder_pooled(pool: impl Into<deadpool_redis::Pool>) -> RedisSessionStoreBuilder {
RedisSessionStoreBuilder {
configuration: CacheConfiguration::default(),
pool: pool.into(),
conn_builder: RedisSessionConnBuilder::Pool(pool.into()),
}
}

/// Create a new instance of [`RedisSessionStore`] using the default configuration.
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`] - a
/// connection string for Redis.
#[cfg(feature = "redis-session")]
pub async fn new<S: Into<String>>(connection_string: S) -> Result<RedisSessionStore, Error> {
/// Creates a new instance of [`RedisSessionStore`] using the default configuration.
///
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`]
/// - a connection string for Redis.
pub async fn new(connection_string: impl Into<String>) -> Result<RedisSessionStore, Error> {
Self::builder(connection_string).build().await
}

/// Create a new instance of [`RedisSessionStore`] using the default configuration.
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`] - a
/// pool object for Redis.
#[cfg(not(feature = "redis-session"))]
pub fn new<P: Into<Pool>>(pool: P) -> RedisSessionStore {
Self::builder(pool).build()
/// Creates a new instance of [`RedisSessionStore`] using the default configuration.
///
/// It takes as input the only required input to create a new instance of [`RedisSessionStore`]
/// - a pool object for Redis.
pub async fn new_pooled(
pool: impl Into<deadpool_redis::Pool>,
) -> anyhow::Result<RedisSessionStore> {
Self::builder_pooled(pool).build().await
}
}

Expand All @@ -144,10 +151,29 @@ impl RedisSessionStore {
#[must_use]
pub struct RedisSessionStoreBuilder {
configuration: CacheConfiguration,
#[cfg(feature = "redis-session")]
connection_string: String,
#[cfg(not(feature = "redis-session"))]
pool: Pool,
conn_builder: RedisSessionConnBuilder,
}

enum RedisSessionConnBuilder {
/// Single connection string.
Single(String),

/// Pre-built connection pool.
#[cfg(feature = "redis-pool")]
Pool(deadpool_redis::Pool),
}

impl RedisSessionConnBuilder {
async fn into_client(self) -> anyhow::Result<RedisSessionConn> {
Ok(match self {
RedisSessionConnBuilder::Single(conn_string) => {
RedisSessionConn::Single(ConnectionManager::new(Client::open(conn_string)?).await?)
}

#[cfg(feature = "redis-pool")]
RedisSessionConnBuilder::Pool(pool) => RedisSessionConn::Pool(pool),
})
}
}

impl RedisSessionStoreBuilder {
Expand All @@ -160,28 +186,15 @@ impl RedisSessionStoreBuilder {
self
}

/// Finalise the builder and return a [`RedisSessionStore`] instance.
///
/// [`RedisSessionStore`]: RedisSessionStore
#[cfg(feature = "redis-session")]
pub async fn build(self) -> Result<RedisSessionStore, Error> {
let client = ConnectionManager::new(redis::Client::open(self.connection_string)?).await?;
/// Finalises builder and returns a [`RedisSessionStore`] instance.
pub async fn build(self) -> anyhow::Result<RedisSessionStore> {
let client = self.conn_builder.into_client().await?;

Ok(RedisSessionStore {
configuration: self.configuration,
client,
})
}

/// Finalise the builder and return a [`RedisSessionStore`] instance.
///
/// [`RedisSessionStore`]: RedisSessionStore
#[cfg(not(feature = "redis-session"))]
pub fn build(self) -> RedisSessionStore {
RedisSessionStore {
configuration: self.configuration,
pool: self.pool,
}
}
}

impl SessionStore for RedisSessionStore {
Expand Down Expand Up @@ -280,18 +293,20 @@ impl SessionStore for RedisSessionStore {
async fn update_ttl(&self, session_key: &SessionKey, ttl: &Duration) -> Result<(), Error> {
let cache_key = (self.configuration.cache_keygen)(session_key.as_ref());

#[cfg(feature = "redis-session")]
self.client
.clone()
.expire::<_, ()>(&cache_key, ttl.whole_seconds())
.await?;
match self.client {
RedisSessionConn::Single(conn) => {
conn.expire::<_, ()>(&cache_key, ttl.whole_seconds())
.await?
}

#[cfg(not(feature = "redis-session"))]
self.pool
.get()
.await?
.expire(&cache_key, ttl.whole_seconds())
.await?;
#[cfg(feature = "redis-pool")]
RedisSessionConn::Pool(pool) => {
pool.get()
.await?
.expire(&cache_key, ttl.whole_seconds())
.await?;
}
}

Ok(())
}
Expand Down

0 comments on commit a8d77af

Please sign in to comment.