Re: HTTP request handler / middleware SRFI
Lassi Kortela 05 Apr 2019 15:18 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.
Good idea :) It's great news that you have all this stuff already.
Snow-Fort and Akku make it really easy to publish packages. The Scheme
community is small and fairly quiet but I've been very pleasantly
surprised at how high quality everything is.
> 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 :-/
I would imagine this can cause problems when composing handlers. If you
use a middleware handler from a library, you should ideally be able to
treat it as a black box that just works. Implicit behavior is convenient
when starting out but tends to be problematic when building big systems
from components because it's not clear where a problem is coming from.
An application writer could start off using return values only. Then
there's no need to worry about flushing headers. Only heavy-duty
apps/middleware would write and flush headers explicitly.
> I'd be willing to help working on this, I've been doing a lot of web
> stuff ;)
Thank you. This is looking great! Also, everyone who has posted in this
thread likely knows more about web tech than I do, which is exactly what
I hoped for ;)
> 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
> ...
> )
You messy library already reads better to me than most of the stable
routing libraries in other languages. Love working with Lisp people :)
> I have parameterized request and response objects, with various
> accessors (scgi:parameter, scgi:request-method, scgi:request-uri,
> set-scgi:response-header!).
That seems like a good starting point for us all.
> There's also some code to write "nice" access logs:
Loggers would go great as their own middlewares IMHO. I recently
factored out the logging stuff from a Go library:
<https://github.com/lassik/go-httplog/> Go also has this same kind of
middleware structure. That made it easy to do fully composable logging.
> 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.
Cool, is this similar to WSGI/Rack/Ring/etc. or something more
comprehensive?
> 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.
Excellent point. This is also one of the strengths of the
request-handler abstraction, but allowing the manual append-header! /
flush-header / append-body! operations complicates it somewhat.
Have you come across <http://httpbin.org/>? It's a web server
established by the author of Python's popular "requests" library, for
the purpose of testing HTTP clients. This doesn't help test our router /
request handler, but it does help with all the peripheral stuff (HTML
form encoding/decoding libraries, etc.) And can help decide what kinds
of test cases to write.
> All of that code is not well-tested or in any way well-written :-/
If people are this motivated, we'll have that sorted out eventually :)