From bcaa35dd2cdc9005f5917185a9a47551db0bd076 Mon Sep 17 00:00:00 2001 From: Automatic website updater <> Date: Tue, 14 Apr 2026 10:09:06 +0100 Subject: [PATCH] Automatic website update --- index.html | 1660 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1654 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 4c8e568..093193f 100644 --- a/index.html +++ b/index.html @@ -45,7 +45,7 @@ ul.no-bullet {list-style: none}
Return a 405 Method Not Allowed response with an Allow header listing ALLOWED-METHODS.
@@ -631,7 +702,7 @@ ALLOWED-METHODS.Start a Safsaf web server.
ROUTES is a list of routes and route-groups (as returned by component @@ -660,6 +731,1380 @@ returns immediately — the caller manages the lifecycle. +
+Next: (safsaf handler-wrappers csrf), Previous: (safsaf), Up: API [Contents][Index]
+Handler wrapper that adds CORS (Cross-Origin Resource Sharing) headers +to responses. +
+Browsers enforce the Same-Origin Policy: scripts on one origin (scheme + +host + port) cannot read responses from a different origin. CORS +relaxes this by letting the server declare which origins, methods, and +headers are permitted. +
+For “simple” requests the browser sends the request and checks the +response headers. For non-simple requests (e.g. PUT/DELETE, custom +headers, or JSON Content-Type) the browser sends a preflight OPTIONS +request first. This wrapper handles both cases. +
+ORIGINS is a list of allowed origin strings, or ’("*") for any. METHODS +is a list of allowed method symbols. HEADERS is a list of allowed +request header name strings. MAX-AGE is the preflight cache duration in +seconds. ALLOW-CREDENTIALS? controls whether credentials (cookies, +auth) are allowed cross-origin. Note: cannot be #t when origins is +’("*"). EXPOSE-HEADERS is a list of response header name strings the +browser may read from JavaScript. +
++Next: (safsaf handler-wrappers exceptions), Previous: (safsaf handler-wrappers cors), Up: API [Contents][Index]
+Default value: +
+#f ++
CSRF token handler wrapper. +
+Ensures a CSRF token cookie is present on every response (generates one +if the request has none). The token is bound to current-csrf-token so +handlers and templates can read it via (current-csrf-token). +
+Token validation is NOT done here — it belongs in the form processing +layer. Use parse-form-params from (safsaf params), which automatically +checks the submitted token against the cookie token. +
+Return an SXML hidden input element for the CSRF token. Use in forms:
+(csrf-token-field) ⇒ (input (@ (type "hidden")
+...)).
+
+Next: (safsaf handler-wrappers logging), Previous: (safsaf handler-wrappers csrf), Up: API [Contents][Index]
+Return a render-error procedure that content-negotiates between +RENDER-HTML and RENDER-JSON based on the request’s Accept header. +
+Default HTML error renderer. In dev mode, shows a rich backtrace page. +In production, returns a minimal HTML page. +
+Default JSON error renderer. In dev mode, includes the backtrace. In +production, returns only the error message. +
+Handler wrapper that catches exceptions from HANDLER and returns an +error response. +
+The response format is content-negotiated from the request’s Accept +header, choosing between HTML and JSON. +
+When LOGGER is provided, exceptions are logged through it. Otherwise, +the backtrace is written to the current error port. In dev mode (DEV? +is #t), the response includes the backtrace and exception details. In +production mode, a generic error is returned. +
+Rendering can be customised at three levels: +
+#:render-error — full override. A procedure (request code message +backtrace-string dev?) -> (values response body) that bypasses content +negotiation entirely. +
+#:render-html — custom HTML rendering. A procedure with the same +signature, called when content negotiation selects HTML. +
+#:render-json — custom JSON rendering. A procedure with the same +signature, called when content negotiation selects JSON. +
+The default RENDER-ERROR content-negotiates between RENDER-HTML and +RENDER-JSON. Providing #:render-html or #:render-json replaces just +that format; providing #:render-error replaces the entire rendering. +
+Return a handler wrapper that catches exceptions and returns an error +response. See exceptions-handler-wrapper for details. +
++Next: (safsaf handler-wrappers max-body-size), Previous: (safsaf handler-wrappers exceptions), Up: API [Contents][Index]
+Handler wrapper that logs each request and response. +
+Logs at LEVEL (default ’INFO) with method, path, status code, and +duration in milliseconds. If LOGGER is given, logs to that logger; +otherwise uses the default logger set via set-default-logger!. +
++Next: (safsaf handler-wrappers security-headers), Previous: (safsaf handler-wrappers logging), Up: API [Contents][Index]
+Return a handler wrapper that rejects requests whose Content-Length +exceeds MAX-BYTES with a 413 Payload Too Large response. +
+HANDLER-413 is a handler (request body-port) -> (values response body) +called when the limit is exceeded; the default returns plain text. +
+Note: this checks the Content-Length header only. Chunked transfers +without Content-Length are not limited by this wrapper. +
++Next: (safsaf handler-wrappers sessions), Previous: (safsaf handler-wrappers max-body-size), Up: API [Contents][Index]
+Handler wrapper that adds security headers to every response. +
+All headers are optional and configurable. Pass #f to disable a header. +Defaults: X-Content-Type-Options: nosniff X-Frame-Options: DENY +Referrer-Policy: strict-origin-when-cross-origin +
+Not set by default (enable explicitly): Strict-Transport-Security (e.g. +"max-age=63072000; includeSubDomains") Cross-Origin-Opener-Policy (e.g. +"same-origin") Permissions-Policy (e.g. "camera=(), microphone=()") +Content-Security-Policy (e.g. "default-src ’self’; script-src ’self’") +Content-Security-Policy-Report-Only — same syntax, for testing policies +without enforcing them +
++Next: (safsaf handler-wrappers trailing-slash), Previous: (safsaf handler-wrappers security-headers), Up: API [Contents][Index]
+Default value: +
+#f ++
Create a session manager for use with session-handler-wrapper. +
+SECRET-KEY is the HMAC signing key (a string). EXPIRE-DELTA is (days +hours minutes), default 30 days. ALGORITHM is the HMAC algorithm, +default sha512. +
+Return a handler wrapper that binds session data from SESSION-MANAGER. +See session-handler-wrapper for details. +
+Return a Set-Cookie header that expires the session cookie. Include in +a response headers list: (redirect-response "/" #:headers (list +(session-delete manager))) +
+Session handler wrapper using signed cookies via (webutils sessions). +
+Reads the session cookie from the request, verifies the HMAC signature, +and binds current-session for the duration of the handler. If no valid +session cookie is present, current-session is #f. +
+Handlers read session data via: (current-session) → session data or #f +
+To set or delete the session, handlers include the appropriate header in +their response using session-set and session-delete: +
+(redirect-response "/" #:headers (list (session-set manager data))) +(redirect-response "/" #:headers (list (session-delete manager))) +
+Return a Set-Cookie header that stores signed DATA in the session +cookie. DATA can be any Scheme value that can be written and read back. +Include in a response headers list: (redirect-response "/" #:headers +(list (session-set manager ’((user-id . 42))))) +
++Next: (safsaf params), Previous: (safsaf handler-wrappers sessions), Up: API [Contents][Index]
+Return a handler wrapper that normalizes trailing slashes. +
+MODE is either ’strip (default) or ’append: ’strip — redirect /foo/ to +/foo ’append — redirect /foo to /foo/ +
+The root path / is always left alone. +
+CODE is the HTTP status code for the redirect (default 301). +
+Use with wrap-routes: (wrap-routes routes +(make-trailing-slash-handler-wrapper #:mode ’append)) +
+Handler wrapper that normalizes trailing slashes in request paths. +
+MODE is either ’strip (default) or ’append: ’strip — redirect /foo/ to +/foo ’append — redirect /foo to /foo/ +
+The root path / is always left alone. +
+CODE is the HTTP status code for the redirect (default 301). +
++Next: (safsaf response-helpers), Previous: (safsaf handler-wrappers trailing-slash), Up: API [Contents][Index]
+Undocumented macro. +
+Undocumented macro. +
+Undocumented macro. +
+Undocumented macro. +
+Return #t if any values in PARSED-PARAMS are invalid. +
+Undocumented procedure. +
+Undocumented procedure. +
+Return a processor that accepts values matching REGEX. +
+Undocumented procedure. +
+Return a processor that accepts only values in CHOICES (a list of +strings). +
+Return a processor that accepts values for which PRED returns true. +
+Undocumented procedure. +
+Return a list of error message strings for NAME, or ’(). Convenient for +rendering form fields with per-field errors. +
+Check PARSED-PARAMS for mutually exclusive parameter groups. GROUPS is +a list of lists of symbols, e.g. ’((limit_results all_results)). If +parameters from the same group co-occur, the later ones are replaced +with <invalid-param> records. +
+Return the <invalid-param> record for NAME, or #f if valid or absent. +
+Serialize PARSED-PARAMS back to a URI query string. Skips invalid +params. Handles multi-value (list) entries. Useful for building +pagination links that preserve current filters. +
+Like parse-params but prepends a CSRF token check. Uses +current-csrf-token from (safsaf handler-wrappers csrf). +
+Parse and transform parameters from RAW-PARAMS according to PARAM-SPECS. +
+RAW-PARAMS is an alist of (string . string) pairs, as returned by +parse-query-string or parse-form-body. +
+PARAM-SPECS is a list of specifications. Each spec is a list whose +first element is the parameter name (a symbol), second is a processor +procedure (string -> value | <invalid-param>), and the rest are keyword +options: +
+(name processor) ; optional (name processor #:required) ; must be +present (name processor #:default value) ; fallback (name processor +#:multi-value) ; collect all occurrences (name processor #:multi-value +#:default value) ; multi-value with fallback (name processor +#:no-default-when (fields) #:default value) ; conditional default +
+Returns an alist of (symbol . value) pairs. Values that fail +validation appear as <invalid-param> records inline. Missing optional +params without defaults are omitted. +
+This record type has the following fields: +
+valuemessage+Next: (safsaf router), Previous: (safsaf params), Up: API [Contents][Index]
+Return a 400 Bad Request response. +
+Build a new response based on RESPONSE, preserving its version, status +code, and reason phrase. HEADERS defaults to the existing headers; +override it to modify them. +
+Use this in handler wrappers that need to adjust headers on an inner +handler’s response without losing any response fields. +
+Return a Set-Cookie header pair that expires cookie NAME. Wraps +(webutils cookie) delete-cookie. +
+Return a 403 Forbidden response. +
+Return an HTML response by streaming SHTML to the client. SHTML is an +SXML/SHTML tree as accepted by write-shtml-as-html. CHARSET defaults to +"utf-8". +
+Return a 500 Internal Server Error response. +
+Return a JSON response. STR is the JSON string to send. +
+Write LST as a JSON array to PORT, applying PROC to each element to +produce a JSON-serializable value. Each element is written individually +via scm->json so the entire array need not be held in memory. +
+Return a handler that serves static files from ROOT-DIR. +
+The handler expects route params to contain a wildcard capture (the file +path segments). Use with a wildcard route: +
+(route ’GET ’(. path) (make-static-handler "/path/to/public")) +
+Supports If-Modified-Since for 304 responses. CACHE-CONTROL, if given, +is a Cache-Control value in Guile’s header format — an alist, e.g. +’((max-age . 3600)) or ’((no-cache)). +
+Works with /gnu/store paths: files with a very low mtime (as produced by +the store’s timestamp normalization) use the process start time as +Last-Modified instead, so that conditional requests behave sensibly. +
+Return the most appropriate MIME type symbol for REQUEST from SUPPORTED. +
+Checks the URL path extension first (.json, .html, .txt) — if present +and the implied type is in SUPPORTED, it wins. Otherwise, walks the +Accept header and returns the first type that appears in SUPPORTED. +Falls back to the first element of SUPPORTED if nothing matches. +
+EXTENSIONS is an alist mapping file extension strings to MIME type +symbols, used for path-based negotiation. Defaults to +%negotiation-extensions. +
+Return a 404 Not Found response. +
+Return a 413 Payload Too Large response. +
+Return a redirect response to PATH (a string). +
+Write ALIST as a JSON object to PORT, streaming each value as it is +produced. If a value in the alist is a procedure, it is called with +PORT so it can write its own JSON representation directly. Otherwise +the value is serialized via scm->json. +
+Return a Set-Cookie header pair suitable for inclusion in a response +headers alist. Wraps (webutils cookie) set-cookie. +
+Example: (values (build-response #:headers (list (set-cookie-header +"session" token #:path "/" #:http-only #t #:secure #t))) "ok") +
+Return a JSON response whose body is written incrementally by THUNK. +THUNK is a procedure of one argument (the output port). Use +scm-alist->streaming-json and list->streaming-json-array inside THUNK to +write JSON without materializing the entire response in memory. +
+Return a plain text response. STR is the text string to send. +
++Next: (safsaf templating), Previous: (safsaf response-helpers), Up: API [Contents][Index]
+Undocumented macro. +
+Return the list of child routes and groups of ROUTE-GROUP. +
+Return the name of ROUTE-GROUP, or #f if unnamed.
+
Return the prefix pattern of ROUTE-GROUP. +
+Return #t if OBJ is a <route-group>.
+
Return the handler procedure of ROUTE. +
+Return the HTTP method of ROUTE. +
+Return the name of ROUTE, or #f if unnamed.
+
Return the URL pattern of ROUTE. +
+Return #t if OBJ is a <route>.
+
Default value: +
+#f ++
Default value: +
+() ++
Compile a route tree (route, route-group, or list) into two values: 1. +An ordered list of <compiled-route> records ready for matching. 2. A +<reverse-routes> record for use with path-for. +
+The last route must be a catch-all (’* pattern with a rest parameter) so +that every request is handled. +
+Scan COMPILED-ROUTES for routes whose path matches PATH-SEGMENTS, +collecting their HTTP methods. The last route (the catch-all) is +excluded. Returns a deduplicated list of method symbols, or ’() if no +route’s path matches. +
+Create an empty route group with PREFIX. Children can be added later +with route-group-add-children!. +
+Find the first matching route for METHOD and PATH-SEGMENTS. Returns +(values handler bindings) on match, or (values #f #f) on no match. +
+Generate a URL path for a named route within GROUP. +
+GROUP is a route-group value. NAME is either a symbol naming a route +within GROUP, or a list of symbols for nested lookup where the last +element is the route name and preceding elements are child group names. +
+(path-for routes ’users) (path-for routes ’user ’((id . "42"))) +(path-for routes ’(api items) ’((id . "7"))) +
+PARAMS is an alist mapping capture symbols to string values, or to a +list of strings for rest parameters. +
+Optional keyword arguments: #:query — alist of query parameters ((key . +value) ...) #:fragment — fragment string (without the leading #) +#:relative? — if #t, omit the leading / +
+Create a route. METHOD is a symbol, list of symbols, or ’* for any. +PATTERN is a list of segments: strings (literal), symbols (capture), +two-element lists (predicate capture: (proc name)), with optional dotted +tail (wildcard capture). HANDLER is a procedure (request body-port) -> +(values response body). NAME is an optional symbol used for reverse +routing with path-for. +
+Create a route group. PREFIX is a pattern list (same syntax as route +patterns). CHILDREN is an ordered list of routes and route-groups. NAME +is an optional symbol for nested path-for lookups. +
+Append NEW-CHILDREN to GROUP’s child list. +
+Apply WRAPPERS to every handler in ROUTES, which may be a route, +route-group, or list of either. Returns a new structure with wrapped +handlers. When multiple wrappers are given, the first wrapper in the +list wraps outermost (runs first on the request, last on the response). +
++Next: (safsaf utils), Previous: (safsaf router), Up: API [Contents][Index]
+Return an HTML response that streams SHTML to the client. +
+SHTML is an SHTML tree that may contain procedures. Each procedure is
+called as (proc port) during output and should write HTML to the
+port. Static parts are rendered via htmlprag.
+
(streaming-response + `(*TOP* + (*DECL* DOCTYPE html) + (html (head (title "My Page")) + (body (h1 "Hello") + ,(lambda (port) + (write-shtml-as-html '(p "dynamic") port)))))) +
Write SHTML to PORT, like write-shtml-as-html from htmlprag, but
+any procedure encountered in the tree is called as (proc port)
+and may write directly to PORT.
+
This allows mixing static SHTML with dynamic streaming sections: +
+(write-shtml-as-html/streaming + `(html (body (h1 "Title") + ,(lambda (port) (display "dynamic" port)) + (footer "bye"))) + port) +
Static parts are rendered via htmlprag’s shtml->html, then
+interleaved with procedure calls at output time.
+
+Previous: (safsaf templating), Up: API [Contents][Index]
+Extract text fields from multipart PARTS as an alist of (name . value). +File upload parts (those with a filename parameter) are excluded. +
+Read and parse a URL-encoded form body from REQUEST. Returns an alist +of string key-value pairs. +
+Read and parse a multipart/form-data body from REQUEST. Returns a list +of <part> records from (webutils multipart). Use parts-ref, +parts-ref-string, part-body, etc. to access parts. +
+Parse the query string from REQUEST. Returns an alist of string +key-value pairs, or ’() if no query string. +
+Return the value of cookie NAME from REQUEST, or DEFAULT if not found. +
+Return the cookies from REQUEST as an alist of (name . value) pairs. +Returns ’() if no Cookie header is present. Importing (webutils cookie) +registers the Cookie header parser with (web http). +
+| Jump to: | < + |
|---|
| Index Entry | Section | ||
|---|---|---|---|
| | |||
| < | |||
<invalid-param>: | safsaf_params | ||
| | |||
| Jump to: | < + |
|---|