NEW: Fenrir v4.1.2 — 56 Bug Fixes, Performance Optimizations, 1331 Tests, 5-Framework Benchmark! Read the changelog
sessions.md
docs sessions.md

Sessions

Fenrir provides multiple session backends for storing user data across requests.

Session Usage with Context Locals

Access the current session via the session context local, imported from fenrir:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from fenrir import Fenrir, session

app = Fenrir()
app.config["SECRET_KEY"] = "your-secret-key"

@app.get("/set")
async def set_session():
    session["user_id"] = 123
    session["theme"] = "dark"
    return {"status": "set"}

@app.get("/get")
async def get_session():
    user_id = session.get("user_id")
    return {"user_id": user_id}

@app.get("/clear")
async def clear_session():
    session.clear()
    return {"status": "cleared"}

The session object is a dict-like object that automatically tracks modifications and is saved to the response at the end of each request.


SessionMixin

Base class for all session objects. A dict subclass that tracks whether the session has been modified or accessed:

1
2
3
4
5
6
7
8
9
from fenrir.sessions import SessionMixin

class CustomSession(SessionMixin):
    pass

s = CustomSession()
print(s.modified)  # False
s["key"] = "value"
print(s.modified)  # True

Tracking behavior:

Operation Sets modified
session["key"] = value Yes
del session["key"] Yes
session.clear() Yes
session.pop("key") Yes
session.update(...) Yes
session["key"] (read only) No (only sets accessed)

SecureCookieSession

Cookie-based session (the default). Session data is serialized, signed, and stored in a cookie on the client:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from fenrir import Fenrir
from fenrir.sessions import SecureCookieSession

app = Fenrir()
app.config["SECRET_KEY"] = "your-secret-key"

@app.get("/set")
async def set_session():
    session["user_id"] = 123
    return {"status": "set"}

ServerSideSession

Server-side session with a sid (session ID) attribute. The session data is stored server-side; only the session ID is sent to the client as a cookie:

1
2
3
4
5
6
7
8
from fenrir.sessions import ServerSideSession

s = ServerSideSession()
s.sid = "abc123"
s["user_id"] = 123

print(s.sid)        # "abc123"
print(s.modified)   # True

SessionInterface (Abstract Base Class)

Base class for all session backends. Subclass this to implement custom storage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from fenrir.sessions import SessionInterface, SessionMixin

class SessionInterface:
    def open_session(self, app, request) -> SessionMixin:
        """Load and return a session from the request."""
        raise NotImplementedError()

    def save_session(self, app, session, response):
        """Save the session to the response."""
        raise NotImplementedError()

SecureCookieSessionInterface

The default session interface. Serializes session data with itsdangerous.URLSafeTimedSerializer, signs it, and stores it in a cookie:

1
2
3
4
5
6
from fenrir import Fenrir
from fenrir.sessions import SecureCookieSessionInterface

app = Fenrir()
app.config["SECRET_KEY"] = "your-secret-key"
app.session_interface = SecureCookieSessionInterface()

How it works:

  • open_session() reads the cookie, verifies the signature, and returns a SecureCookieSession.
  • save_session() serializes the session, signs it, and sets the cookie on the response.
  • If the session is empty and modified, the cookie is deleted.

InMemorySessionBackend

A simple in-memory session store for testing and single-process deployments. Sessions are stored in a Python dict with TTL-based expiration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from fenrir.sessions import InMemorySessionBackend

backend = InMemorySessionBackend()

# Store session data
backend.set("sid123", {"user_id": 1}, ttl=3600)

# Retrieve session data
data = backend.get("sid123")
print(data)  # {"user_id": 1}

# Delete session
backend.delete("sid123")

Expired sessions are automatically cleaned up on access.


In-Memory Sessions

Server-side sessions backed by InMemorySessionBackend:

1
2
3
4
5
6
from fenrir import Fenrir
from fenrir.sessions import InMemorySessionInterface

app = Fenrir()
app.config["SECRET_KEY"] = "your-secret-key"
app.session_interface = InMemorySessionInterface(ttl=3600)

Parameters:

  • backend: Custom InMemorySessionBackend instance
  • ttl: Session time-to-live in seconds (default: 86400)

Redis Sessions

Server-side sessions backed by Redis. Supports both sync and async Redis clients:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from fenrir import Fenrir
from fenrir.sessions import RedisSessionInterface

app = Fenrir()
app.config["SECRET_KEY"] = "your-secret-key"

# With fakeredis (for testing)
import fakeredis
redis_client = fakeredis.FakeRedis()
app.session_interface = RedisSessionInterface(redis_client=redis_client)

# With real Redis
import redis
redis_client = redis.Redis(host="localhost", port=6379, db=0)
app.session_interface = RedisSessionInterface(redis_client=redis_client, ttl=7200)

Parameters:

  • redis_client: Redis client instance (required)
  • prefix: Key prefix (default: "session:")
  • ttl: Session time-to-live in seconds (default: 86400)

Install Redis support: pip install fenrir-framework[redis]


Configuration Keys

Key Default Description
SECRET_KEY (required for cookie sessions) Secret key for signing cookies via itsdangerous
SESSION_COOKIE_NAME "session" Cookie name
SESSION_COOKIE_DOMAIN None Cookie domain
SESSION_COOKIE_PATH "/" Cookie path
SESSION_COOKIE_SECURE True Only send cookie over HTTPS
SESSION_COOKIE_HTTPONLY True Prevent JavaScript access to cookie
SESSION_COOKIE_SAMESITE None SameSite cookie attribute ("Strict", "Lax", "None")
SESSION_TTL 86400 Session TTL in seconds (server-side backends)

Session Classes Reference

Class Description
SessionMixin Base dict subclass with modified/accessed tracking
SecureCookieSession Cookie-based session (default)
ServerSideSession Server-side session with sid attribute
SessionInterface Abstract base class for session backends
SecureCookieSessionInterface Default cookie-based session interface
InMemorySessionBackend In-memory storage backend
InMemorySessionInterface In-memory session interface
RedisSessionInterface Redis-backed session interface

Custom Session Backend

Implement SessionInterface for custom backends:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from fenrir import Fenrir
from fenrir.sessions import SessionInterface, SessionMixin

class CustomSession(SessionMixin):
    pass

class CustomSessionInterface(SessionInterface):
    def open_session(self, app, request):
        session_id = request.cookies.get("session_id")
        if session_id:
            data = self.load_from_storage(session_id)
            session = CustomSession(data)
        else:
            session = CustomSession()
        return session

    def save_session(self, app, session, response):
        if session.modified:
            self.save_to_storage(session)
            response.set_cookie("session_id", session.sid)

    def load_from_storage(self, session_id):
        # Implement your storage lookup here
        pass

    def save_to_storage(self, session):
        # Implement your storage save here
        pass

app = Fenrir()
app.session_interface = CustomSessionInterface()

Session Lifecycle

  1. Request arrivesSessionInterface.open_session() reads the session from the cookie/storage and returns a session object.
  2. During request handling — Handlers read/write session["key"]. The modified flag is set automatically.
  3. Response sentSessionInterface.save_session() checks if the session was modified, and if so, persists it and sets/updates the cookie.
Edit on GitHub Last Updated: Oct 20, 2018
© 2026 Fenrir Project.
main*
v4.1.2
Ln 1, Col 1
UTF-8
Prettier
Light Mode
Markdown