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

Open
isaacs opened this Issue Apr 20, 2012 · 5 comments

3 participants

@isaacs

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()
})
@mikeal
Owner

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.

@isaacs

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()
s.pipe(f)
req.socket = f

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

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

@mikeal
Owner

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.

@isaacs

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.

@kesla

Hi!

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