Friday 19 February 2016

Express: a clean way to keep track of passing data / dependencies between middleware? Or just attach properties to req?

A common pattern in Express is to have a pipeline of middlewares that prepare data/services for the route handler:bodyParser middleware parses the params and definesreq.bodyyour middleware checks for req.body.widgetId and maybe fetches some data and attaches it to req.widgetyour router handler for /show-widget readsreq.widget to return a response, or skips the response if it's absent by calling next()a final 404 handler catches any skipped routes and generates a 404 responseThe problematic issuesIt works and is nicely composable (you can always switch out individual middleware implementations, as long as they manipulate req in the same way). But two issues bother me:req namespace already has stuff on it, it gets polluted and collisions could happen between middlewares that are careless.Careful documentation is needed to keep track of which properties are expected and which are attached by each middleware, and all the dependencies between middleware.Making services available to middleware/handlersWhen middleware/handlers need access to services like DB or external API access, I'd like to benefit from the composability and inversion of control of middleware too, so the perfect simple solution looks is to attach services to req or to req.app (which is a pointer to the express app, for app-wide services).It's especially relevant when the service is request-specific, like if I have req.user.oauthAccessToken so the external API call concerns this particular req. I could have a service called req.fetchUserDataUsingAccessToken() which is attached to req by a middleware and which depends on that token property being present. But that's a further extension of the issues above.Testing middlewareI can test middleware functions in isolation, by feeding them a contrived req object and afterwards checking that req was mutated as expected. That's great. But I don't have anything helping me ensure that the full middleware stack is wired up properly and in the right dependency order.What I already looked atResearch is pointing me in the direction of express-based dependency injection, and I found express-di and express-dinja but they engage in monkey-patching or they mess with the standard req, res, next signature so I'm hesitant. I want to keep things easy to grok, and to stick to standard Express "idioms" as much as possible.So, any suggestions for how to manage lots of middleware while keeping it decoupled, composable and easily testable?What are the idiomatic, best-practices solutions?

Submitted February 19, 2016 at 03:49PM by ecmascript2038

No comments:

Post a Comment