💾 Archived View for rwv.io › 2021-08-29-dezhemini-wrappers.gmi captured on 2023-06-16 at 15:59:46. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

Dʒɛmɪni wrappers (aka middleware)

Dʒɛmɪni now supports wrappers which means you can run code before and after a request, manipulating both the request parameters and the response status, meta and/or body. Why? Superpowers! Let's start with a couple of examples.

Here's how dʒɛmɪni (roughly) implements request logging now:

(define (wrap handler)
  (lambda (req)
    (log-info "server=~s url=~s"
              (assq 'server-name req)
              (assq 'url req))
    (handler req)))

Given a "handler" function "wrap" composes a new handler which first logs the server name and the url and than handles the request like it normally would. The above only deals with the "before" situation. Here's an example of manipulating the response:

(define (wrap handler)
  (lambda (req)
    (call-with-values
     (lambda () (handler req))
     (case-lambda
       [(status meta body)
        (if (string-prefix? meta "text/")
            (values status meta
                    (string-replace (if (string? body)
                                      body
                                      (read-string 65536 body)) ; nobody needs more than 64k, right?
                                    "http"
                                    "that-other-protocol"))
            (values status meta body))]
       [res
        (apply values res)]))))

Above is a wrapper which changes all occurrences of "http" in a returned text response with "that-other-protocol". Note the use of (call-with-values .. (case-lambda ..)) because a handler will return either 3 or 2 values; 3 (status, meta and body) for "20"-responses and 2 (status and meta) for all other responses.

A wrapper is configured on the commandline like:

racket dezhemini.rkt -W my-fancy-wrapper.rkt example.com:root

Other possible applications of this:

The "examples/wrappers" directory also includes an example to automatically set "lang" according to the directory name the requests is served from.

Enjoy! And please, don't be shy and share your wrappers (and handlers) on the dezhemini mailing list.

https://lists.sr.ht/~rwv/dezhemini

Cheers,

R.

--

📅 2021-08-29

🏷 dʒɛmɪni, announcement

📧 hello@rwv.io

CC BY-NC-SA 4.0