Reference · Cookies and sessions
session
session() -> mapWhat it does
The visitor's session: the map set_session stored, read from the signed cookie the
browser sent back, or {} when there is none. It works in any function the request
runs: a route, a server fn a component calls, a helper, a pipeline stage. Outside a
request (a job, a script) it is {}. See Headers, cookies and
sessions.
Examples
route GET /me { let id = session().user ?? reply 401 "Log in first" db.one("select id, name from users where id = ?", id)}server fn save_note(text: str) { let id = session().user ?? return err("Sign in first") db.exec("insert into notes (user_id, text) values (?, ?)", id, text)}print(session())print(session().user)print(session().user ?? "nobody"){}nullnobodyEdge cases
- No session is
{}, never null, so a field of it is null and??gives the default without a check for null first. - A session past its time, one signed for another tenant or another mounted program,
or one whose signature does not match, is no session:
{}. A request carrying two valid session cookies has no session either: one of them was planted. - Reading it never renews it: a session ends when its time is up however often the
visitor comes. Call
set_sessionagain on the requests that count as use. - After
set_sessionin the same run,session()gives the new map at once; afterend_session,{}again. So it is inparallel's functions. - Each request reads the cookie it came with: two requests of one visitor that change the session at once do not see each other's change, and the last cookie wins. Keep what must not be lost in a table keyed by an id in the session.
- Inside a
liveloader it is the viewer's session, since the loader runs as a call from the page.unwatched(() => session())reads it without following anything.
print(session() == {}, len(keys(session())))set_session({ user: 7, role: "admin" })print(session(), session().role)end_session()print(session())true 0{ user: 7, role: "admin" } admin{}Errors
session() takes no arguments and never fails: a missing, expired or forged cookie is
{}. Guarding a route is the program's own ??:
let id = session().user ?? "guest"print(id)guestfn me() = session().user == null ? null : db.one("select id, name from users where id = ?", session().user)fn me_or_login(back: str) = me() ?? reply 303 redirect(`/login?next=${url_encode(back)}`)Chaining
The map is a value like any other: a field, a default, a lookup.
set_session({ user: 7, roles: ["editor", "admin"] })print(session().roles | map(upper))print(session() | keys)["EDITOR", "ADMIN"]["user", "roles"]See also
set_session, end_session, cookie, unwatched
Thread 0 posts
On session(): questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.
Edit this page on GitHub · every example's output was made by running it (tools/refcheck.mjs) · questions on Discord or r/quillo