81 lines
2.3 KiB
Markdown
81 lines
2.3 KiB
Markdown
|
|
# Safsaf
|
||
|
|
|
||
|
|
<p align="center">
|
||
|
|
<img src="doc/logo.svg" alt="Safsaf" width="150">
|
||
|
|
</p>
|
||
|
|
|
||
|
|
A web framework for [GNU Guile](https://www.gnu.org/software/guile/),
|
||
|
|
using [Guile Fibers](https://codeberg.org/guile/fibers) and the [Guile
|
||
|
|
Knots](https://cbaines.codeberg.page/guile-knots/) web server.
|
||
|
|
|
||
|
|
Developed based off of the Guix Data Service and Nar Herder codebases,
|
||
|
|
written using Claude Code running Claude Opus 4.6.
|
||
|
|
|
||
|
|
## Quick Example
|
||
|
|
|
||
|
|
```scheme
|
||
|
|
(use-modules (safsaf)
|
||
|
|
(safsaf router)
|
||
|
|
(safsaf response-helpers))
|
||
|
|
|
||
|
|
(define routes
|
||
|
|
(list
|
||
|
|
(route 'GET '() (lambda (request body-port)
|
||
|
|
(text-response "Hello, world!")))
|
||
|
|
(route '* '* (lambda (request body-port)
|
||
|
|
(not-found-response)))))
|
||
|
|
|
||
|
|
(run-safsaf routes #:port 8080)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Design
|
||
|
|
|
||
|
|
Safsaf aims for functional over imperitive configuration and to be
|
||
|
|
minimal but very extensible.
|
||
|
|
|
||
|
|
Suspendable ports in Guile plus Guile Fibers is used both for Safsaf
|
||
|
|
internals, but should also be used for user applications where
|
||
|
|
possible and suitable.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
- **Request router** with parameterised segments, wildcards, nested
|
||
|
|
groups, and reverse routing (`path-for`)
|
||
|
|
- **Handler wrappers** (middleware) applied per-route or per-group via
|
||
|
|
`wrap-routes`
|
||
|
|
- **Included handler wrappers**: logging, CORS, CSRF protection,
|
||
|
|
sessions (signed cookies), security headers, trailing-slash
|
||
|
|
normalization, exception handling
|
||
|
|
- **Request helpers**: form body parsing, multipart parsing, query
|
||
|
|
strings, cookies
|
||
|
|
- **Response helpers**: HTML/SXML, JSON, redirects, plain text, static
|
||
|
|
files with `Last-Modified` / `Cache-Control`
|
||
|
|
- **Parameter parsing**: declarative param specs with built-in
|
||
|
|
processors, CSRF integration, and error inspection
|
||
|
|
|
||
|
|
### Wishlist
|
||
|
|
|
||
|
|
- Internationalization support
|
||
|
|
- Server sent events (SSE) support
|
||
|
|
- WebSockets support
|
||
|
|
|
||
|
|
## Other Guile web frameworks
|
||
|
|
|
||
|
|
- **GNU Artanis** https://artanis.dev/
|
||
|
|
- **schingle** https://github.com/petelliott/schingle
|
||
|
|
|
||
|
|
## Dependencies
|
||
|
|
|
||
|
|
- GNU Guile 3.0+
|
||
|
|
- [Guile Knots](https://forge.cbaines.net/cbaines/guile-knots) (web server, resource pools)
|
||
|
|
- Guile Webutils (multipart, cookies, sessions)
|
||
|
|
- [Guile JSON](https://github.com/aconchillo/guile-json) 4.x
|
||
|
|
- [Guile Lib](https://www.nongnu.org/guile-lib/) (htmlprag, logging)
|
||
|
|
|
||
|
|
A Guix development environment is provided via `guix-dev.scm` and
|
||
|
|
`.envrc` (direnv).
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
LGPL-3.0-or-later
|