Session
StruxJS provides a session system that persists data across HTTP requests using a session ID stored in a cookie. Session data is automatically loaded at the start of each request and saved when the response is sent.
How It Works
Every request that goes through routes/web.ts is automatically wrapped with the StartSession middleware. On each request it:
- Reads the session ID from the
struxjs_sessioncookie - Loads the session payload from the configured driver (file, database, redis, or memory)
- Makes the session available via
request.session() - Saves the session back to the driver when the response finishes
API routes (routes/api.ts) do not have session middleware applied - sessions are web-only by default.
Configuration
Environment variables
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_TABLE=sessions
SESSION_COOKIE=struxjs_session
SESSION_DOMAIN=
SESSION_SECURE=falseconfig/session.ts
import { env } from "struxjs";
export default {
driver: env("SESSION_DRIVER", "file"),
lifetime: Number(env("SESSION_LIFETIME", 120)), // minutes
table: env("SESSION_TABLE", "sessions"),
cookie: env("SESSION_COOKIE", "struxjs_session"),
path: "/",
domain: env("SESSION_DOMAIN", undefined),
secure: env("SESSION_SECURE", false),
http_only: true,
same_site: "lax" as const,
};Cookie name
The StartSession middleware currently uses a hardcoded cookie name of struxjs_session. The SESSION_COOKIE config value is available in config/session.ts but is not yet consumed by the middleware - the cookie name cannot be changed via environment variable at this time.
Available Drivers
file (default)
Stores each session as a JSON file in storage/framework/sessions/. Each file is named by session ID and includes an expiry timestamp checked on read.
SESSION_DRIVER=filememory
Stores sessions in a static Map inside the running process. Sessions are lost on server restart.
Best for: automated testing, local development.
SESSION_DRIVER=memorydatabase
Stores sessions in a SQL table (or MongoDB collection). Supports both relational databases and MongoDB.
SESSION_DRIVER=databaseYou need to create the sessions table first. Generate and run the migration:
npx strux make:migration create_sessions_table
npx strux migrateThe table must have these columns:
table.string("id").primary();
table.integer("user_id").nullable();
table.text("payload").notNullable();
table.integer("last_activity").notNullable();The table name defaults to sessions and is configurable via SESSION_TABLE.
redis
Stores sessions in Redis using ioredis. TTL is enforced natively by Redis. Session keys are prefixed with strux_session: by default (configurable via REDIS_PREFIX).
SESSION_DRIVER=redisRedis connection parameters are read from config/redis.ts (default connection) and the same REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_DB environment variables.
Accessing the Session
Via request.session()
Inside a Controller action, inject request and call .session():
import { Request, Response } from "struxjs";
export class UserController {
public async store(request: Request, response: Response) {
const session = request.session();
session.put("user_id", 42);
const userId = session.get("user_id");
}
}Via the session() global helper
Outside of a controller - in services, middleware, or event listeners - use the session() global helper:
import { session } from "struxjs";
const store = session();
store.put("key", "value");Session Methods
All methods are available on the SessionStore instance returned by request.session() or session().
put(key, value) / set(key, value)
Store a value in the session:
session.put("theme", "dark");
session.set("locale", "en"); // aliasget(key, defaultValue?)
Retrieve a value from the session. Checks both persistent attributes and flash data. Returns the default if the key is not found:
const theme = session.get("theme");
const locale = session.get("locale", "en");has(key) / exists(key)
Check whether a key is present in the session:
if (session.has("user_id")) {
// user is logged in
}forget(key) / delete(key)
Remove a specific key from the session:
session.forget("temp_token");
session.delete("temp_token"); // aliasflush()
Remove all data from the session - both persistent attributes and flash data:
session.flush();all()
Get all session data (persistent + flash) as a plain object:
const data = session.all();getId()
Get the current session ID:
const id = session.getId();regenerate()
Destroy the current session and generate a new ID. The old session data is cleared from the driver. Used to prevent session fixation attacks (called automatically by Auth.login()):
session.regenerate();Flash Messages
Flash data is stored in the session for one request only. It is automatically available on the very next request and then discarded.
session.flash(key, value)
Store a flash value directly:
session.flash("status", "Profile updated successfully.");Reading flash data
Flash data is read with the same session.get() method:
const status = session.get("status");Flashing on redirect
The RedirectResponse methods .with(), .withInput(), and .withErrors() make it easy to flash data as part of a redirect.
.with(key, value) / .with(object)
Flash one or more key-value pairs and redirect:
return response.redirect("/dashboard")
.with("status", "Settings saved.");
// Multiple keys at once
return response.redirect("/dashboard")
.with({ status: "Saved.", level: "success" });.withInput()
Flash all current request input so it can be repopulated in the next form render:
return response.redirect().back()
.withInput();Access flashed input in the next request via request.old():
const email = request.old("email");
const name = request.old("name", ""); // with defaultIn .strux templates, old() is automatically available:
<input type="email" name="email" value="{{ old('email') }}">.withErrors(errors)
Flash validation errors to the session. On the next request, errors are automatically injected into template context as the errors variable:
return response.redirect().back()
.withInput()
.withErrors({ email: "Email address is already taken." });In templates, errors is available as a ErrorBag:
@if(errors.has('email'))
<p>{{ errors.first('email') }}</p>
@endifApplying the Session Middleware Manually
The StartSession middleware is auto-applied to all web routes. For custom route groups or API routes where you need session support, apply it explicitly:
import { Route } from "struxjs";
import { StartSession } from "struxjs";
// Apply to a specific route
Route.get("/checkout", [CheckoutController, "show"])
.middleware(StartSession);
// Apply to a group
Route.middleware([StartSession]).group(() => {
Route.get("/cart", [CartController, "index"]);
Route.post("/cart", [CartController, "store"]);
});To exclude session from specific web routes (e.g. webhooks):
import { StartSession } from "struxjs";
Route.post("/webhooks/stripe", [WebhookController, "handle"])
.withoutMiddleware(StartSession);
// Or using the string alias
Route.post("/webhooks/stripe", [WebhookController, "handle"])
.withoutMiddleware("session");Driver Comparison
| Driver | Persistence | Shared across servers | TTL enforcement | Best for |
|---|---|---|---|---|
file | Yes (disk) | No | On read | Default, single-server |
memory | No | No | On read | Testing, local dev |
database | Yes (SQL/Mongo) | Yes | On read | Multi-server, no Redis |
redis | Yes (Redis) | Yes | Native (atomic) | Production, high-traffic |