Integrating `core.async` with `httpcore5-h2`

53 views
Skip to first unread message

Dimitrios Piliouras

unread,
Oct 31, 2020, 2:45:39 PM10/31/20
to Clojure Mailing List

Hi folks,

For some reason, the server component of the apache http-components [1] library doesn't get any love from the Clojure community. This is particularly strange to me, given the early/broad adoption of the client component (i.e. clj-http). In any case, I took version 5 for a spin, and in particular the async-server aspect of it, as I wanted to see whether it would integrate cleanly/nicely with core.async channels.

The ring model of async handlers taking 3 arguments, albeit necessary, is hard to work with.  Not only does it feel kind of magic - it is actually non-trivial to (correctly) propagate the `respond` and `raise` callbacks across the middleware stack (which can lead to bugs). The way I see it, it would be much nicer if the response's body was enough to distinguish whether this is a sync or async response. In other words, returning a core.async channel as the body should suffice to treat this as an async response. 

I spent a few hours today, and came up with this server wrapper [2]. If you need convincing that this works, evaluate the two expressions at the bottom of the file (inside a `comment` expression), and cURL into it from your terminal (per the comments). The actual construct which enables a channel to act as body can be seen here (`ChannelContentProducer`) [3]. 

The convention (for handlers) is simple. Use `promise-chan` for single response, but regular `chan` for streaming responses. That is it! No respond/raise indirection - just putting into the channel (and closing it when streaming). Other than that, honors the ring-spec (wrt requests).

So there you have it - async from the ground-up, HTTP2 supporting, ring-friendly web-server prototype (in less than 250 lines). 

Kind regards,

Dimitrios


[1]: https://hc.apache.org/httpcomponents-core-5.0.x/index.html

[2]: https://github.com/jimpil/asynctopia/blob/master/src/asynctopia/server/embedded.clj

[3]: https://github.com/jimpil/asynctopia/blob/master/src/asynctopia/server/channel_body.clj

bartuka

unread,
Nov 2, 2020, 12:26:16 PM11/2/20
to clo...@googlegroups.com

Cool! Thanks for sharing, I was looking for a simple web-server
prototype in order to study its internal.
Reply all
Reply to author
Forward
0 new messages