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)