Listening for end of response with Node/Express.JS
I'm currently working with CoffeeScript, Node, Express, and Redis to deliver on a quick'n'easy contract I've been put in charge of. This is the first time I've used any of these technologies in a proper commercial deliverables type project, and I have to say, it's been an absolute delight.
An issue I ran into was I wanted to reduce the boilerplate on handling requests, so I wrote a quick route middleware in Express to create a client connection to Redis, assigning the connection to the request object for easy use . I also wanted to be clever and have this same middleware clean up after itself when the request ended. That is, I wanted the middleware to QUIT the Redis connection when the response had been sent.
Consulting the Express/Connect/Node docs yielded no clues as to how to do this, the closest hint I found was from the Node docs indicating that a http.ServerResponse is a WritableStream. I noticed WritableStreams had a "close" event that is supposed to be called when the Stream is no longer writable. I assumed that if you call .end() on a response then it should trigger this event, so my initial middleware looked like this:
setupRedisClient = (req, res, next) =>
req.redisClient = require("redis").createClient()
cleanup = =>
console.log "it worked!"
req.redisClient.quit()
res.on "close", cleanup
res.on "error", cleanup
next()
I tried using this middleware in a route, and was sad to see that the event was not being triggered.
As a last resort I started digging through the Node source, and lo and behold! I found what I was looking for in lib/http.js. Turns out when you .end() your http response, it will emit a "finish" event.
Now my Redis middleware looks like so:
setupRedisClient = (req, res, next) =>
req.redisClient = require("redis").createClient()
cleanup = =>
req.redisClient.quit()
res.on "finish", cleanup
res.on "error", cleanup
next()
Incoming routes that need a Redis connection simply add this middleware, and hey presto! They can use req.redisClient to their hearts content. Once a response is sent back to the client, or an error occurs with the request, the Redis connection will be cleaned up automagically! Hurrah!
