middleware: Replace .onWrite method with the ability to return a different writable stream #13

isaacs opened this Issue Apr 20, 2012 · 5 comments

3 participants


So, right now, middleware can do this:

middleware.on("request", function (req, res) {
  res.onWrite = function (chunk) {
    // do something, and return a different chunk synchronously

however, there's no way to:

  1. Know when the response is ended
  2. Do something asynchronously

Really, what you want to do is hijack the actual request/response with a filter of some sort.

For example, a gzip middleware might conditionally want to attach a decoding filter onto the request, and an encoding filter onto the response.

Consider this:

gzipMiddleware.on("request", function (req, res) {
  // attach a filter in front of the readable request stream.
  // Methods proxied: pipe, pause, resume
  // .on() attaches listeners to filter instead for: data, end, close
  if (requestCompressed(req)) req.filter = zlib.Unzip()

  // attach a filter in front of the writable response stream.
  // Methods proxied: write, end
  // .on() attaches listeners to filter instead for: pause, resume
  if (responseCanBeCompressed(req)) res.filter = zlib.Gzip()

i'd rather rip all the middleware out.

we should just implement JSON support inline, it already requires specifial hooks outside of the "middleware" stuff.


Hm. Yeah, I guess you can just do exactly the same thing by listening to app.on("request", myMiddlewareBits).

That still doesn't make it possible to attach filters, though. I suppose you could probably do something like this:

var s = req.socket
var f = zlib.Unzip()
req.socket = f

var s = res.socket
var f = zlib.Gzip()
res.socket = f

but that's of course getting super overly familiar with implementation internals.


yup, the only thing the framework needs hooks for are conditions that will require IO to complete and might need to be required for a route.

auth is one, sessions are another. I want to change the way auth is implemented in to a more generic "condition" system we can use for sessions and other things.


But, no, you could still do json support as a purely external middleware thing if you could attach filters. Just define a stream filter that takes in Objects and spits out JSON, and another that takes JSON and spits out objects. The only other part is setting the content-type and accept headers appropriately.



I've implemented a gzip-middleware for tako https://github.com/kesla/tako-gzip. The suggested code that @isaacs wrote earlier doesn't work, since that gzips the headers also.
Instead I overwrote the _work and _end-methods in the response...
Heavily dependent on implementation internails...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment