save sessions after middleware that way middleware can mutate the session and it will properly save

Commit 7018315 · patx · 2025-12-03T20:29:29-05:00

Changeset
70183156fee663c4faac7375a8d7144edc50c4bc
Parents
85f5d5e6d3cd4a40feca3fdd446b65a0d7decced

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/micropie.py b/micropie.py
index 3fd49ce..b5c8acc 100644
--- a/micropie.py
+++ b/micropie.py
@@ -649,14 +649,7 @@ class App:
                 response_body = json.dumps(response_body)
                 extra_headers.append(("Content-Type", "application/json"))
 
-            # Persist session
-            if request.session:
-                session_id = cookies.get("session_id") or str(uuid.uuid4())
-                await self.session_backend.save(session_id, request.session, SESSION_TIMEOUT)
-                if not cookies.get("session_id"):
-                    extra_headers.append(("Set-Cookie", f"session_id={session_id}; Path=/; SameSite=Lax; HttpOnly; Secure;"))
-
-            # HTTP middlewares (after)
+            # HTTP middlewares
             for mw in self.middlewares:
                 if result := await mw.after_request(request, status_code, response_body, extra_headers):
                     status_code, response_body, extra_headers = (
@@ -665,6 +658,23 @@ class App:
                         result.get("headers", extra_headers)
                     )
 
+            # Session persistence after middlewares so they can mutate request.session
+            session_id = cookies.get("session_id")
+
+            if request.session:
+                # New or updated session
+                if not session_id:
+                    session_id = str(uuid.uuid4())
+                    extra_headers.append((
+                        "Set-Cookie",
+                        f"session_id={session_id}; Path=/; SameSite=Lax; HttpOnly; Secure;"
+                    ))
+                await self.session_backend.save(session_id, request.session, SESSION_TIMEOUT)
+            elif session_id:
+                # Empty session and existing cookie -> treat as logout/delete
+                await self.session_backend.save(session_id, {}, 0)
+
+
             # Handle async generators (e.g., SSE)
             if hasattr(response_body, "__aiter__"):
                 sanitized_headers: List[Tuple[str, str]] = []