diff --git a/HISTORY.md b/HISTORY.md index 712d3d5a..b1fd4c36 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -16,6 +16,7 @@ unreleased - perf: hoist regex declaration - perf: use regex to extract mime * perf: enable strict mode + * perf: simplify threshold detection 1.4.4 / 2015-05-11 ================== diff --git a/index.js b/index.js index 1db1d76d..de571127 100644 --- a/index.js +++ b/index.js @@ -49,7 +49,7 @@ function compression(options) { } return function compression(req, res, next){ - var compress = true + var length var listeners = [] var write = res.write var on = res.on @@ -68,34 +68,26 @@ function compression(options) { res.write = function(chunk, encoding){ if (!this._header) { - // if content-length is set and is lower - // than the threshold, don't compress - var len = Number(res.getHeader('Content-Length')) - checkthreshold(len) - this._implicitHeader(); + this._implicitHeader() } + return stream ? stream.write(new Buffer(chunk, encoding)) - : write.call(res, chunk, encoding); + : write.call(this, chunk, encoding) }; res.end = function(chunk, encoding){ - var len - - if (chunk) { - len = Buffer.isBuffer(chunk) - ? chunk.length - : Buffer.byteLength(chunk, encoding) - } - if (!this._header) { - len = Number(this.getHeader('Content-Length')) || len - checkthreshold(len) + // estimate the length + if (!this.getHeader('Content-Length')) { + length = chunkLength(chunk, encoding) + } + this._implicitHeader() } if (!stream) { - return end.call(res, chunk, encoding) + return end.call(this, chunk, encoding) } // write Buffer for Node.js 0.8 @@ -119,15 +111,8 @@ function compression(options) { return this } - function checkthreshold(len) { - if (compress && len < threshold) { - debug('size below threshold') - compress = false - } - } - function nocompress(msg) { - debug('no compression' + (msg ? ': ' + msg : '')) + debug('no compression: %s', msg) addListeners(res, on, listeners) listeners = null } @@ -142,8 +127,9 @@ function compression(options) { // vary vary(res, 'Accept-Encoding') - if (!compress) { - nocompress() + // content-length below threshold + if (Number(res.getHeader('Content-Length')) < threshold || length < threshold) { + nocompress('size below threshold') return } @@ -225,6 +211,20 @@ function addListeners(stream, on, listeners) { } } +/** + * Get the length of a given chunk + */ + +function chunkLength(chunk, encoding) { + if (!chunk) { + return + } + + return !Buffer.isBuffer(chunk) + ? Buffer.byteLength(chunk, encoding) + : chunk.length +} + /** * No-operation function * @private diff --git a/test/compression.js b/test/compression.js index 64f37938..9d227fad 100644 --- a/test/compression.js +++ b/test/compression.js @@ -394,6 +394,18 @@ describe('compression()', function(){ .expect(shouldNotHaveHeader('Content-Encoding')) .expect(200, '....', done) }) + + it('should work with res.end(null)', function (done) { + var server = createServer({ threshold: 1000 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end(null) + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip') + .expect(200, '', done) + }) }) describe('when "Accept-Encoding: gzip"', function () {