glimr/session/session

Session

Gleam is immutable, but sessions need mutable state that persists across multiple reads and writes within a single request handler. An OTP actor per request provides that mutability safely — each operation is a message, so concurrent access is serialized. The middleware reads the actor’s final state after the handler returns to persist only what actually changed, avoiding unnecessary store writes.

Types

Deprecated: use glimr/session.Session instead

Context requires a Session field at construction time, but the actor can’t start until a request arrives with cookie data. The Empty variant satisfies the type system during boot without allocating an actor, while Live wraps the real per-request actor subject. Making the type opaque prevents callers from pattern matching on the variant and coupling to the internal representation.

pub opaque type Session

Values

pub fn all(session: Session) -> dict.Dict(String, String)

Deprecated: use glimr/session.all instead

Bulk reads are needed for serialization (e.g. the cookie store encoding the full session into a signed cookie) and for debugging. Returns a snapshot — further mutations after this call won’t be reflected in the returned dict.

pub fn cookie_store() -> store.SessionStore

Deprecated: use glimr/session.cookie_store instead

Cookie-based sessions avoid server-side storage entirely — the signed cookie is the store. This is ideal for small payloads under ~4KB where the simplicity of zero infrastructure outweighs the per-request bandwidth cost.

pub fn empty() -> Session

Deprecated: use glimr/session.empty instead

Context is constructed at boot before any HTTP request arrives, so there’s no cookie data to seed a real session actor. This returns a no-op handle where all reads return empty values and all writes are silently ignored, avoiding the need for Option(Session) throughout the framework.

pub fn error(session: Session, field: String) -> String

Deprecated: use glimr/session.error instead

Showing inline validation errors next to the field that failed is way better than a generic “something went wrong” banner. The validator flashes each field’s first error so templates can display it right where it matters.

<p l-if="session.error(ctx.session, 'email') != ''" class="text-red-600">
  {{ session.error(ctx.session, "email") }}
</p>
pub fn flash(session: Session, key: String, value: String) -> Nil

Deprecated: use glimr/session.flash instead

Flash messages provide one-shot feedback across redirects (e.g. “Item saved successfully”). Storing them separately from regular session data and clearing them after one read ensures they appear exactly once without the handler needing to manage cleanup.

pub fn forget(session: Session, key: String) -> Nil

Deprecated: use glimr/session.forget instead

Removing a key marks the session dirty so the middleware persists the deletion. Fire-and-forget like put since the caller doesn’t need to wait for confirmation.

pub fn get(session: Session, key: String) -> Result(String, Nil)

Deprecated: use glimr/session.get instead

Reads go through actor.call (synchronous) because the caller needs the value immediately to make decisions in the handler. Returns Error(Nil) for missing keys so callers can distinguish absence from an empty string.

pub fn get_flash(session: Session, key: String) -> String

Deprecated: use glimr/session.get_flash instead

Most flash reads happen in templates where an empty string is the natural “no flash” value. Returning “” instead of a Result avoids wrapping every template interpolation in a case expression.

pub fn get_flash_or(
  session: Session,
  key: String,
) -> Result(String, Nil)

Deprecated: use glimr/session.get_flash_or instead

When the handler needs to distinguish between “no flash was set” and “flash was set to an empty string”, this Result- returning variant provides that distinction. get_flash delegates here and unwraps for the common case.

pub fn has(session: Session, key: String) -> Bool

Deprecated: use glimr/session.has instead

Existence checks are synchronous (actor.call) because the caller typically branches on the result immediately, e.g. to decide whether to redirect an unauthenticated user.

pub fn has_error(session: Session, field: String) -> Bool

Deprecated: use glimr/session.has_error instead

Templates often need to conditionally show error styling or error messages. Checking error() != "" works but reads awkwardly in template expressions. This gives a clean boolean for l-if directives.

<p l-if="session.has_error(ctx.session, 'email')" class="text-red-600">
  {{ session.error(ctx.session, "email") }}
</p>
pub fn has_flash(session: Session, key: String) -> Bool

Deprecated: use glimr/session.has_flash instead

Templates often need to conditionally render a flash banner only when a message exists. A Bool check is cleaner than matching on a Result when the value itself isn’t needed for the conditional.

pub fn id(session: Session) -> String

Deprecated: use glimr/session.id instead

The session ID is needed by the store to look up or persist the session data. Exposing it lets middleware and store implementations access it without reaching into the actor’s internal state directly.

pub fn invalidate(session: Session) -> Nil

Deprecated: use glimr/session.invalidate instead

Logout and account deletion need to destroy all session state and issue a new ID so the old session cookie can never be reused. The invalidated flag tells middleware to delete the old entry from the store rather than just overwriting it.

pub fn old(session: Session, field: String) -> String

Deprecated: use glimr/session.old instead

Nobody wants to retype an entire form because one field failed validation. After a redirect back, the validator stashes the old values as flash data so templates can repopulate inputs automatically.

<input type="email" name="email" :value="session.old(ctx.session, 'email')" />
pub fn put(session: Session, key: String, value: String) -> Nil

Deprecated: use glimr/session.put instead

Writes use process.send (fire-and-forget) because the caller doesn’t need confirmation — the actor serializes all mutations and the middleware reads the final state after the handler returns.

pub fn regenerate(session: Session) -> Nil

Deprecated: use glimr/session.regenerate instead

After login, the session ID must change to prevent session fixation attacks — an attacker who planted a known session ID before authentication can’t hijack the post-login session if the ID rotates. Data is preserved so the user doesn’t lose pre-login state.

pub fn setup(session_store: store.SessionStore) -> Nil

Deprecated: use glimr/session.setup instead

Caches the given session store in persistent_term so the session middleware can access it on every request without threading it through function arguments. Call this once at boot after creating a store from any driver.

Search Document