Skip to main content

Crate rainier_session

Crate rainier_session 

Source
Expand description

§rainier-session

Sessions: the Session bag a handler reads and writes, the SessionStore port it is persisted through, and the StartSession middleware that ties them to a cookie.

use rainier_session::{MemorySessionStore, SessionRequestExt, StartSession, SessionStore};
use rainier_http::{Request, Response};
use rainier_middleware::{Middleware, Pipeline};
use std::sync::Arc;

let store = Arc::new(MemorySessionStore::default());
let start: Arc<dyn Middleware> =
    Arc::new(StartSession::new(Arc::clone(&store) as Arc<dyn SessionStore>));

let response = Pipeline::new()
    .through_arc(start)
    .then(|request: Request| async move {
        let session = request.session().expect("StartSession ran");
        session.put("user_id", 42u64).unwrap();
        Response::text("ok")
    })
    .run(Request::builder().build())
    .await;

assert!(response.header("set-cookie").is_some());

§The session is on the request, not on a facade

A session facade can work in PHP because the container rebinds a request-scoped session per request. Rainier’s facades resolve from a process-global application, so there is nothing honest for Session::instance().get(…) to return — with two requests in flight, which one would it be?

So the split is explicit:

request.session()this request’s bag
SessionManager (the Session facade)the store and its settings

The facade is for what genuinely is application-wide: reading or destroying a session by id, and collecting expired ones.

§Flash data

flash stores a value for exactly one further request — the redirect-then-show-a-message pattern, with nothing to remember to clean up:

let session = Session::new();
session.flash("status", "Saved.").unwrap();

// …the request ends, and the next one can read it.
let next = Session::restore("id", session.age_and_take());
assert_eq!(next.string("status").as_deref(), Some("Saved."));

// …and the one after that cannot.
let later = Session::restore("id", next.age_and_take());
assert!(!later.has("status"));

§Drivers

DriverSurvives a restartSharedRevocableNote
MemorySessionStorenonoyesdevelopment
DatabaseSessionStoreyesyesyesnever evicts
CacheSessionStoredependsyesyesexpires itself; can evict
CookieSessionStoreyesyesnono server state at all

A memory store behind a load balancer makes a user’s session appear to vanish and reappear as they are routed around, which looks like a bug in your login code and is not.

The cookie driver is the odd one: the whole session travels encrypted in the cookie, so there is nothing to store and nothing to expire — and nothing to revoke either. A session you cannot see is a session you cannot end.

Re-exports§

pub use cache::CacheSessionStore;
pub use cookie::CookieSessionStore;
pub use database::DatabaseSessionStore;
pub use database::SessionRow;
pub use driver::SessionDriver;
pub use manager::SessionConfig;
pub use manager::SessionManager;
pub use middleware::SessionRequestExt;
pub use middleware::StartSession;
pub use session::generate_session_id;
pub use session::Session;
pub use session::SessionData;
pub use session::TOKEN_KEY;
pub use store::is_well_formed;
pub use store::MemorySessionStore;
pub use store::SessionStore;

Modules§

cache
CacheSessionStore — sessions in a Cache, and so in Redis, a Redis Cluster, or Memcached.
cookie
CookieSessionStore — the whole session, encrypted, in the cookie.
database
DatabaseSessionStore — sessions on the database you already have.
driver
Where session state lives — SessionDriver.
manager
SessionManager — the store and its settings, as one container-storable value.
middleware
StartSession — the middleware that loads a session and writes it back.
session
The session bag — Session and the SessionData that is persisted.
store
Where sessions live — the SessionStore port and its implementations.