Sessions allow your web framework to maintain state between requests from the same client. This is crucial for features like login persistence, shopping carts, or user preferences.
What is a Session?
HTTP is stateless by design, meaning each request is independent. Sessions provide a way to associate multiple requests with a user by storing data on the server side and linking it via a session ID cookie.
How Sessions Work
- When a client connects, generate a unique session ID.
- Store session data on the server (in-memory, file, or database) keyed by that ID.
- Send the session ID back as a cookie.
- On subsequent requests, read the cookie to retrieve session data.
Generating Session IDs
Session IDs should be:
- Unique
- Hard to guess (secure)
- Usually a long random string
Use Python’s secrets
module:
import secrets def generate_session_id(): return secrets.token_hex(16)
Storing Session Data
For a simple framework, use a dictionary:
sessions = {}
Each session ID maps to a dict of user data:
sessions[session_id] = {"user_id": 123, "cart": []}
Setting and Reading Cookies
When sending responses, include a Set-Cookie
header:
Set-Cookie: session_id=abc123; Path=/; HttpOnly
In incoming requests, parse the Cookie
header:
def parse_cookies(headers): cookies = {} cookie_header = headers.get("Cookie", "") for pair in cookie_header.split(";"): if "=" in pair: key, value = pair.strip().split("=", 1) cookies[key] = value return cookies
Middleware Example for Sessions
A middleware that loads or creates a session:
def session_middleware(request, next_handler): cookies = parse_cookies(request["headers"]) session_id = cookies.get("session_id") if not session_id or session_id not in sessions: session_id = generate_session_id() sessions[session_id] = {} request["session"] = sessions[session_id] response = next_handler(request) # Add Set-Cookie header if new session created if "Set-Cookie" not in response.get("headers", {}): response.setdefault("headers", {})["Set-Cookie"] = f"session_id={session_id}; Path=/; HttpOnly" return response
Using Sessions in Handlers
Handlers can access request["session"]
to read or write session data:
def dashboard(request): user = request["session"].get("user") if not user: return {"status": 401, "body": b"Unauthorized"} return {"status": 200, "body": f"Welcome, {user}".encode()}
Security Considerations
- Use
HttpOnly
andSecure
flags on cookies where appropriate - Implement session expiration and cleanup
- Consider storing sessions outside memory for scalability
- Protect against session fixation and hijacking
Wrap-Up
Adding basic session support to your lightweight framework enables persistent user experiences. While simple in concept, proper session management is key to building real-world web applications.
Want to dive deeper? Check out my 20-page PDF guide: Building a Lightweight Python Web Framework from Scratch
Top comments (0)