Jonathan Ong
Jonathan Ong

Reputation: 20325

compress/gzip/deflate streaming content using res.write

var express = require('express')

var app = module.exports = express()

function getImages(callback) {
  callback()
}

app
.set('views', __dirname + '/views')
.set('view engine', 'jade')
.get('/stream/images', function(req, res) {
  res.render('layout', function(err, body) {
    res.type('html')
    res.write(body.replace('</body></html>', ''))
    getImages(function(err) {
      res.render('streams/images', function(err, body) {
        var html = '<div class="layout-stream">' + body + '</div>'
        res.write(
          "<script>$('.pagelet-layout-stream').replaceWith(" + 
          JSON.stringify(html) + 
          "); emitter.emit('check:stream');</script>"
        )
        res.write("<script>emitter.emit('load');</script>")
        res.write('</body></html>')
        res.end()
      })
    })
  })
})
.listen(3013)

This works exactly as intended. However, when I .use(express.compress()) (before .get to be exact), the page no longer streams. In other words, the express.compress() seems to wait until the response is finished, then gzip the entire response, then send it. I would like each res.write to send a gzipped response (or specifically, every drain). How can I compress the response correctly?

Edit 1 - I tried this:

var stream = zlib.createGzip()
stream.pipe(res)

stream.write(/* stuff */)
stream.end()

This works exactly like express.compress(). I'm not sure whether the browser just doesn't parse the body until it has the whole thing, or it doesnt send the body until the response is complete.

Upvotes: 1

Views: 1514

Answers (1)

Jonathan Ong
Jonathan Ong

Reputation: 20325

var stream = zlib.createGzip()
stream._flush = zlib.Z_SYNC_FLUSH
stream.pipe(res)

stream.write(/* stuff */)
stream.end()

Upvotes: 1

Related Questions