expressjs/compression

Chunked encoding is broken after using this middleware

Sw0rdstream opened this issue · 1 comments

Demo to reproduce the problem:

const express = require('express')
const compression = require('compression');
const app = express()
const port = 3001

// after using compression, the first chunk will not be sent until the second chunk is written.
app.use(compression());
app.get('/', (req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('Transfer-Encoding', 'chunked');
  res.write('<html><body>First chunk <br>');
  process.nextTick(function (){
    // simulate a long wait in order to confirm chunk encoding in browser easily
    for(var i = 0; i<4000000000; i++){}
    res.write('Second chunk </body></html>');
    res.end();
  });
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

Once removing the code of using compression(), the chunked encoding will work well.

Yes, that is expected due to how compression works. The compression algorithm will wait for enough data to compress a full chunk. This module provides the res.flush() method in order to signal that you want the compression algorithm to prematurely get flushed, resulting in a diminished compression ratio.