dream: cookie-backed sessions + in-memory store + 30 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m4s

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 14:35:46 +00:00
parent b5a273cc99
commit 55ec0b8f64
4 changed files with 343 additions and 1 deletions

View File

@@ -56,7 +56,7 @@ The five types: `request`, `response`, `handler = request -> response`, `middlew
- `dream-no-middleware` — identity.
- Logger: `(dream-logger next req)` — logs method, path, status, timing.
- Content-type sniffer.
- [ ] **Sessions** in `lib/dream/session.sx`:
- [x] **Sessions** in `lib/dream/session.sx`:
- Cookie-backed session middleware.
- `dream-session-field req key`, `dream-set-session-field req key val`.
- `dream-invalidate-session req`.
@@ -128,6 +128,20 @@ Confirm scope before starting; some of these may be addable as Dream-internal he
`dream-log-line` formats one line. `dream-content-type` sniffs body (`<`→html,
`{`/`[`→json, else text) only when the handler left Content-Type unset. Bonus
`dream-set-header` and `dream-tap-request` combinators.
- **2026-06-07 — Sessions** (`lib/dream/session.sx`, 30 tests). Solved the
request→response mutation-visibility problem the way Dream does: the cookie carries
only a session id; fields live in an injectable back-end store (the mapping table's
`(perform (:session-get …))`). `dream-memory-sessions` is an in-memory store built
on a `set!`-mutated captured `let` binding (no `ref`/`atom` in base env);
`dream-perform-sessions` is the production back-end. `dream-sessions backend`
middleware reads/creates the id, attaches `{:sid :io}` to the request, and emits a
`Set-Cookie` (HttpOnly, SameSite=Lax) only for new sessions. Handler API:
`dream-session-field` / `dream-set-session-field` / `dream-session-all` /
`dream-invalidate-session` / `dream-session-id`. Also added shared cookie infra
(`dr/parse-cookies`, `dream-cookie(s)`, `dr/build-cookie`, `dream-set-cookie`,
`dream-resp-cookies`, `dream-drop-cookie`) — outgoing cookies accumulate in a
`:set-cookies` list on the response so multiple Set-Cookie headers don't collide;
reused by flash + CSRF. Full counter round-trip verified across three requests.
## Blockers