Modular bidi and ring middleware

81 views
Skip to first unread message

ex...@expez.com

unread,
Feb 25, 2015, 8:18:19 AM2/25/15
to modul...@googlegroups.com
Hi

I'm using modular.http-kit.Webserver to serve up the routes in a modular.bidi.Router.  Where is the intended extension point for adding ring middleware?

Malcolm Sparks

unread,
Apr 5, 2015, 12:44:57 PM4/5/15
to modul...@googlegroups.com
This is a good question.

There are 3 ways of adding Ring middleware in a modular project, the right one depends on what you want to do.

1. You can always apply Ring middleware on each individual handler (target). For individual handlers, that's quite straightforward :-

["/index.html" (-> h (wrap-some-middleware) (wrap-some-other-middleware options) (bidi/tag ::index))]

Note that here I'm using bidi's 'tag' function to mark the handler with a tag which can be used in place of the actual handler in a bidi/path-for call.

However, if you have to wrap every handler in your system with the same Ring middleware, this can be a pain (although you can usually automate this pain away with some helper code of your own design).

2. Use bidi's WrapMiddleware wrapper. See https://github.com/juxt/bidi#wrapmiddleware

This can be applied against an entire uri sub-tree, where it makes sense to apply the same Ring middleware consistently against every route, or at least a sub-tree of routes in your URI tree.

3. modular.ring has a component called WebRequestHandlerHead that you can wire up inbetween your chosen web server component and the WebRequestHandler component (typically modular.bidi's router).

In practice, I find the approach in 3. quite awkward and usually opt for 1. with some helper code.

Ring middleware is a very useful tool, but overuse of Ring middleware in applications can end up creating code smells. 

1. Repetition of the same middleware at various parts of the call stack
2. Hidden 'couplings' between various Ring middleware that's been applied
3. Sensitivity to Ring middleware being applied in the correct order
4. Synchronous only - everything forced to happen in a single thread.

It is these issues that mean I tend to avoid depending on Ring middleware in my web projects.

My feeling is that Ring middleware works for simple apps, but when you scale up there are various problems with it. For example, setting the content-type header should really be the responsibility of the handler itself, and better done by libraries such as Liberator and yada which have more context available (relative to an individual middleware wrapper) to make a better determination of the header's value.
Reply all
Reply to author
Forward
0 new messages