Web framework
The demo app
Webglue grows together with a companion application: a small ticket system that uses each library as it arrives.
Layout
| Part | Holds |
|---|---|
libs/tickets | The domain, with no HTTP in it |
apps/web | Routes, handlers, middleware and the supervision tree |
prx webglue watch | A WebSocket client written in Praxis, to watch pushes arrive |
The domain
A ticket is a map, and each transition returns #(:ok ticket) or #(:error reason). A ticket moves from open to assigned, between assigned and on hold, and finally to closed.
(defn assign [ticket who] :spec [map any -> tuple]
(if (open? ticket)
#(:ok (map/merge ticket {:status :assigned :assignee who}))
#(:error :closed)))The HTTP side
The pieces are the ones on Core concepts: the route table, the application function, the supervision tree, validation on raising a ticket, a socket with presence, and a push on every change. A refused transition becomes a 409, a missing login a 401, an unknown ticket a 404.
A session with it
$ prx run --no-halt webglue_demo # WEBGLUE_ADAPTER=wrangler for Wrangler $ curl -d 'subject=Printer is on fire' localhost:4000/tickets #1 [open] Printer is on fire $ curl -X POST localhost:4000/tickets/1/assign log in first # 401 $ curl -X POST -H 'X-Demo-User: jan' localhost:4000/tickets/1/assign #1 [assigned] Printer is on fire -> jan $ curl -X POST -H 'X-Demo-User: jan' localhost:4000/tickets/1/close $ curl -X POST -H 'X-Demo-User: jan' localhost:4000/tickets/1/assign refused: closed # 409 $ websocat ws://localhost:4000/socket/tickets # watch the pushes live $ prx routes webglue.demo.web # print the route table
X-Demo-User is a convenience that skips the cookie session so curl needs no cookie jar; the real sign-in is POST /session with a user field.
What it does not do yet
- No database — the store is in memory, behind the data-layer seam, and stays swappable.
- Identity is a name; there is no authorization.
- Plain text and form bodies; no content negotiation.
- No browser UI — pushes are watched with a WebSocket client.