Re: HTTP request handler / middleware SRFI
Peter 05 Apr 2019 13:58 UTC
> Great! Have you considered publishing the Chez version in Akku?
> <https://akkuscm.org/>
Yes, but it's quite a mess now, it includes support for parsing and
writing cookies, multipart/form-data, application/x-www-form-urlencoded,
and automatic conversion of parameters. Things should be split up into
multiple libraries.
> Do you mean that if the user's handler returns an alist of response
> headers, then you need to ensure that it didn't write anything in the
> body before the server gets the chance to write those headers?
Yes, the problem is if the user writes some data, then tries to add or
modify another header. Also, writing to a temporary string means you
just don't have to care about this, and can write headers whenever you
want (which is nicer for the user).
> So append-to-body! would cause an error unless flush-header has been
> called on that request.
It'd be nicer for the user if the first write to the body would just
flush the headers. I think PHP does it that way. Having to flush
explicitly isn't very nice :-/
> That is the plan :) But we'd need to get some momentum going and do it
> with a view to eventually publishing an SRFI, hence have a draft spec
> from the get go so we remember not to bake in assumptions about the
> particular implementation strategies we happen to be using.
I'd be willing to help working on this, I've been doing a lot of web
stuff ;)
Right now, my API looks a bit like this:
(define-url-handler (get "/" account period)
;; define a handler for "/" that only listens on GET requests.
;; Automatically bind the url parameters `account' and `period' to parameters.
... do something with account and period ...
)
(define-url-handler ((get post) "/foo" (n number) (f symbol))
;; listen to GET and POST, automatically try to convert n to a number
;; and f to a symbol
...
)
I have parameterized request and response objects, with various
accessors (scgi:parameter, scgi:request-method, scgi:request-uri,
set-scgi:response-header!). There's also some code to write "nice"
access logs:
2019-04-05T12:54:17+04 GET /foo?code=XZ6Xroaut [192.168.0.1]
code: "XZ6Xroaut" ()
-> Status: 200
I also have rudimentary support for CSS and a Schemely version of
Javascript:
(define-url-handler (get "/css")
(css-response
(css `(("header.ui.navbar" (background-color "#b1c800"))
(".ui.menu" (margin 0) (border-radius 0))
("header" (flex "0 0 auto") (background-color "#b1c800"))
...))))
(define-url-handler (get "/javascript")
(parenscheme-response
`("use strict"
($ - (lambda ()
(define (dropdown-on-show)
(set-timeout window
(lambda ()
(focus ($ - (ref ($ - ".ui.dropdown.active > input.search") 0))))
500)
#t)
(popup ($ - ".popup-button")
(object :inline #t)))))))
I've found https://github.com/http4k/http4k interesting to look at.
I've also found that making the interface *testable* is very important
(I haven't quite achieved that yet). You really want a nice way to send
a request object in and test things about the response.
All of that code is not well-tested or in any way well-written :-/