How to Configure SessionMiddleware for User Sessions in Air
Add air.SessionMiddleware to your application with a secret_key parameter to enable signed cookie-based sessions accessible via request.session on every incoming request.
Configuring SessionMiddleware for user sessions in the feldroy/air framework requires minimal boilerplate while providing secure, stateful interactions across HTTP requests. Air implements session handling as a thin wrapper around Starlette's SessionMiddleware, exposing a familiar API for storing user-specific data in signed browser cookies. This guide demonstrates the exact implementation details found in the source code and provides production-ready patterns for session management.
Understanding Air's Session Architecture
Air’s session handling is intentionally lightweight, delegating core functionality to Starlette’s battle-tested implementation. In src/air/middleware.py, the SessionMiddleware class inherits directly from starlette.middleware.sessions.SessionMiddleware without overriding behavior, ensuring complete compatibility with Starlette’s session protocol.
When you register this middleware on an air.Air application instance, it performs three critical operations on every request:
- Deserializes the incoming signed cookie into a mutable dictionary attached to
request.session - Validates the cookie signature using your configured
secret_keyto prevent tampering - Serializes any modifications back into the response cookie when the request completes
The session object requires JSON-serializable values only—strings, numbers, lists, and dictionaries. Complex Python objects must be converted before storage.
Basic Configuration
Enable sessions by calling add_middleware() on your Air application instance. The secret_key parameter is mandatory and serves as the cryptographic signing key for cookie integrity.
import air
app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me-in-production")
The middleware re-export in src/air/__init__.py makes air.SessionMiddleware available as a public API, so you do not need to import from the middleware submodule directly.
Reading and Writing Session Data
Once configured, every air.Request object includes a session attribute behaving like a standard Python dictionary. The framework automatically handles cookie parsing and persistence, allowing you to focus on business logic.
from time import time
import air
app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me")
@app.page
async def set_timestamp(request: air.Request):
# Store data in the session dictionary
request.session["first-visited"] = time()
return air.H1("Session initialized")
@app.page
async def show_timestamp(request: air.Request):
# Retrieve data safely using .get() to handle missing keys
timestamp = request.session.get("first-visited")
return air.H1(f"First visited: {timestamp}")
@app.page
async def clear_session(request: air.Request):
# Remove specific keys or clear the entire session
request.session.pop("first-visited", None)
return air.H1("Session cleared")
The cookie is sent to the client only when the response modifies the session. Clearing all keys or setting request.session = {} removes the cookie entirely.
Building Authentication Flows
The session middleware supports complete authentication workflows, as demonstrated in docs/learn/cookbook/authentication.md and validated in tests/test_middleware.py. Store user identifiers and metadata after verification, then check for their presence on protected routes.
import air
from time import time
app = air.Air()
app.add_middleware(air.SessionMiddleware, secret_key="change-me")
@app.page
async def index(request: air.Request):
if "username" in request.session:
return air.layouts.mvpcss(
air.H1(f"Welcome {request.session['username']}"),
air.P(air.A("Logout", href="/logout")),
)
return air.layouts.mvpcss(
air.Form(
air.Label("Name:", for_="username"),
air.Input(name="username", type_="text", required=True),
air.Button("Login", type_="submit"),
action="/login",
method="post",
)
)
@app.post("/login")
async def login(request: air.Request):
form = await request.form()
if username := form.get("username"):
request.session["username"] = username
request.session["logged_in_at"] = time()
return air.RedirectResponse("/", status_code=302)
@app.page
async def logout(request: air.Request):
request.session.pop("username", None)
return air.RedirectResponse("/")
This pattern leverages the immutable nature of signed cookies to maintain authentication state without server-side storage.
Summary
- Air's SessionMiddleware is a direct subclass of Starlette's implementation located in
src/air/middleware.py, providing signed cookie-based session storage. - Configuration requires a
secret_keyparameter passed toapp.add_middleware(air.SessionMiddleware, secret_key="...")to cryptographically sign session cookies. - Data access occurs through
request.session, a mutable dictionary available on all incoming requests that automatically persists changes to the client cookie. - Storage constraints limit values to JSON-serializable types only; the cookie is cleared when the session becomes empty.
- Authentication patterns follow standard session-based workflows: store identifiers on login, validate presence on protected routes, and delete keys on logout.
Frequently Asked Questions
What is the difference between air.SessionMiddleware and Starlette's SessionMiddleware?
air.SessionMiddleware inherits directly from starlette.middleware.sessions.SessionMiddleware without modifications, as defined in src/air/middleware.py. Air re-exports this class in src/air/__init__.py to provide a unified namespace while maintaining 100% API compatibility with Starlette's session implementation.
What data types can be stored in request.session?
The session dictionary accepts only JSON-serializable values: strings, integers, floats, booleans, lists, and dictionaries. Attempting to store custom objects, datetime instances, or binary data will raise a serialization error when Air processes the response. Convert complex types to strings or ISO timestamps before storage.
How do I clear or delete a session?
Remove specific keys using request.session.pop("key", None) to avoid KeyError exceptions. To clear the entire session, either delete all keys individually or set request.session to an empty dictionary. The middleware detects empty sessions and instructs the browser to delete the cookie automatically.
Where is the session data stored?
Session data resides entirely in the client-side signed cookie. Air does not maintain server-side session storage by default. The secret_key signs the cookie to prevent client tampering, but the data payload is visible to the user (though cryptographically verified). Keep session data small and avoid storing sensitive information like passwords or credit card numbers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →