diff --git a/README.md b/README.md index 682517b4..19bc7c90 100644 --- a/README.md +++ b/README.md @@ -43,102 +43,64 @@ as compressing will transform the body. #### Options -`compression()` accepts these properties in the options object. In addition to -those listed below, [zlib](http://nodejs.org/api/zlib.html) options may be -passed in to the options object or -[brotli](https://nodejs.org/api/zlib.html#zlib_class_brotlioptions) options. +`compression()` accepts these properties in the options object. -##### chunkSize +##### encodings -Type: `Number`
-Default: `zlib.constants.Z_DEFAULT_CHUNK`, or `16384`. +Type: `Object`
-See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) -regarding the usage. +Handles the configurations for each encoding. Setting options.encodings[encoding] = false will disable that encoding. -##### filter - -Type: `Function` - -A function to decide if the response should be considered for compression. -This function is called as `filter(req, res)` and is expected to return -`true` to consider the response for compression, or `false` to not compress -the response. - -The default filter function uses the [compressible](https://www.npmjs.com/package/compressible) -module to determine if `res.getHeader('Content-Type')` is compressible. - -##### level - -Type: `Number`
-Default: `zlib.constants.Z_DEFAULT_COMPRESSION`, or `-1` - -The level of zlib compression to apply to responses. A higher level will result -in better compression, but will take longer to complete. A lower level will -result in less compression, but will be much faster. - -This is an integer in the range of `0` (no compression) to `9` (maximum -compression). The special value `-1` can be used to mean the "default -compression level", which is a default compromise between speed and -compression (currently equivalent to level 6). - - - `-1` Default compression level (also `zlib.constants.Z_DEFAULT_COMPRESSION`). - - `0` No compression (also `zlib.constants.Z_NO_COMPRESSION`). - - `1` Fastest compression (also `zlib.constants.Z_BEST_SPEED`). - - `2` - - `3` - - `4` - - `5` - - `6` (currently what `zlib.constants.Z_DEFAULT_COMPRESSION` points to). - - `7` - - `8` - - `9` Best compression (also `zlib.constants.Z_BEST_COMPRESSION`). - -**Note** in the list above, `zlib` is from `zlib = require('zlib')`. +Example: -##### memLevel +```js +const compression = require('compression') +const express = require('express') + +const app = express() + +app.use( + compression({ + encodings: { + br: { + params: { + [zlib.constants.BROTLI_PARAM_QUALITY]: 6 + } + }, + gzip: { + level: zlib.constants.Z_BEST_SPEED + }, + deflate: false // Disable Deflate compression + } + }) +) +``` -Type: `Number`
-Default: `zlib.constants.Z_DEFAULT_MEMLEVEL`, or `8` +###### Supported Encodings -This specifies how much memory should be allocated for the internal compression -state and is an integer in the range of `1` (minimum level) and `9` (maximum -level). +- **`br` (Brotli):** -See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) -regarding the usage. +This specifies the options for configuring Brotli. See [Node.js documentation](https://nodejs.org/api/zlib.html#class-brotlioptions) for a complete list of available options. -##### brotli +- **gzip:** -Type: `Object` +This specifies the options for configuring gzip. See [Node.js documentation](https://nodejs.org/api/zlib.html#class-options) for a complete list of available options. -This specifies the options for configuring Brotli. See [Node.js documentation](https://nodejs.org/api/zlib.html#class-brotlioptions) for a complete list of available options. +- **deflate:** +This specifies the options for configuring deflate. See [Node.js documentation](https://nodejs.org/api/zlib.html#class-options) for a complete list of available options. -##### strategy - -Type: `Number`
-Default: `zlib.constants.Z_DEFAULT_STRATEGY` +##### filter -This is used to tune the compression algorithm. This value only affects the -compression ratio, not the correctness of the compressed output, even if it -is not set appropriately. +Type: `Function` - - `zlib.constants.Z_DEFAULT_STRATEGY` Use for normal data. - - `zlib.constants.Z_FILTERED` Use for data produced by a filter (or predictor). - Filtered data consists mostly of small values with a somewhat random - distribution. In this case, the compression algorithm is tuned to - compress them better. The effect is to force more Huffman coding and less - string matching; it is somewhat intermediate between `zlib.constants.Z_DEFAULT_STRATEGY` - and `zlib.constants.Z_HUFFMAN_ONLY`. - - `zlib.constants.Z_FIXED` Use to prevent the use of dynamic Huffman codes, allowing - for a simpler decoder for special applications. - - `zlib.constants.Z_HUFFMAN_ONLY` Use to force Huffman encoding only (no string match). - - `zlib.constants.Z_RLE` Use to limit match distances to one (run-length encoding). - This is designed to be almost as fast as `zlib.constants.Z_HUFFMAN_ONLY`, but give - better compression for PNG image data. +A function to decide if the response should be considered for compression. +This function is called as `filter(req, res)` and is expected to return +`true` to consider the response for compression, or `false` to not compress +the response. -**Note** in the list above, `zlib` is from `zlib = require('zlib')`. +The default filter function uses the [compressible](https://www.npmjs.com/package/compressible) +module to determine if `res.getHeader('Content-Type')` is compressible. ##### threshold @@ -154,14 +116,6 @@ at the time the response headers are written, then it is assumed the response is _over_ the threshold. To guarantee the response size can be determined, be sure set a `Content-Length` response header. -##### windowBits - -Type: `Number`
-Default: `zlib.constants.Z_DEFAULT_WINDOWBITS`, or `15` - -See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) -regarding the usage. - ##### enforceEncoding Type: `String`
diff --git a/index.js b/index.js index 5dd09c7b..c0f380d1 100644 --- a/index.js +++ b/index.js @@ -36,11 +36,9 @@ module.exports.filter = shouldCompress * @private */ var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/ -var SUPPORTED_ENCODING = ['br', 'gzip', 'deflate', 'identity'] +var ENCODING_OPTIONS = ['br', 'gzip', 'deflate'] var PREFERRED_ENCODING = ['br', 'gzip'] -var encodingSupported = ['gzip', 'deflate', 'identity', 'br'] - /** * Compress response data with gzip / deflate. * @@ -50,12 +48,14 @@ var encodingSupported = ['gzip', 'deflate', 'identity', 'br'] */ function compression (options) { - var opts = options || {} - var optsBrotli = { - ...opts.brotli, + const opts = options || {} + const encodingOpts = opts?.encodings + const encodingSupported = ENCODING_OPTIONS.filter(enc => encodingOpts?.[enc] !== false) + const optsBrotli = { + ...encodingOpts?.br, params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4, // set the default level to a reasonable value with balanced speed/ratio - ...opts.brotli?.params + ...encodingOpts?.br?.params } } @@ -187,10 +187,10 @@ function compression (options) { // compression method var negotiator = new Negotiator(req) - var method = negotiator.encoding(SUPPORTED_ENCODING, PREFERRED_ENCODING) + var method = negotiator.encoding(encodingSupported, PREFERRED_ENCODING) // if no method is found, use the default encoding - if (!req.headers['accept-encoding'] && encodingSupported.indexOf(enforceEncoding) !== -1) { + if (!req.headers['accept-encoding'] && encodingSupported.includes(enforceEncoding)) { method = enforceEncoding } @@ -202,11 +202,13 @@ function compression (options) { // compression stream debug('%s compression', method) - stream = method === 'gzip' - ? zlib.createGzip(opts) - : method === 'br' - ? zlib.createBrotliCompress(optsBrotli) - : zlib.createDeflate(opts) + if (method === 'gzip') { + stream = zlib.createGzip(encodingOpts?.gzip) + } else if (method === 'br') { + stream = zlib.createBrotliCompress(optsBrotli) + } else if (method === 'deflate') { + stream = zlib.createDeflate(encodingOpts?.deflate) + } // add buffered listeners to stream addListeners(stream, stream.on, listeners) diff --git a/test/compression.js b/test/compression.js index 78173c33..6f855989 100644 --- a/test/compression.js +++ b/test/compression.js @@ -51,6 +51,19 @@ describe('compression()', function () { .expect(200, 'hello, world', done) }) + it('should skip if content-encoding is identity', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'identity') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, done) + }) + it('should set Vary', function (done) { var server = createServer({ threshold: 0 }, function (req, res) { res.setHeader('Content-Type', 'text/plain') @@ -459,215 +472,304 @@ describe('compression()', function () { }) }) - describe('when "Accept-Encoding: gzip"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('encodings', function () { + describe('when "Accept-Encoding: gzip"', function () { + it('when gzip is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { gzip: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip') - .expect('Content-Encoding', 'gzip', done) - }) + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - it('should return false writing after end', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') - assert.ok(res.write() === false) - assert.ok(res.end() === false) + request(server) + .get('/') + .set('Accept-Encoding', 'gzip') + .expect('Content-Encoding', 'gzip', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip') - .expect('Content-Encoding', 'gzip', done) - }) - }) + it('should return false writing after end', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + assert.ok(res.write() === false) + assert.ok(res.end() === false) + }) - describe('when "Accept-Encoding: deflate"', function () { - it('should respond with deflate', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + request(server) + .get('/') + .set('Accept-Encoding', 'gzip') + .expect('Content-Encoding', 'gzip', done) }) - - request(server) - .get('/') - .set('Accept-Encoding', 'deflate') - .expect('Content-Encoding', 'deflate', done) }) - }) - describe('when "Accept-Encoding: br"', function () { - it('should respond with br', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: deflate"', function () { + it('should respond with deflate', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate') + .expect('Content-Encoding', 'deflate', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'br') - .expect('Content-Encoding', 'br', done) + it('when deflate is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { deflate: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) + }) }) - }) - describe('when "Accept-Encoding: br" and passing compression level', function () { - it('should respond with br', function (done) { - var params = {} - params[zlib.constants.BROTLI_PARAM_QUALITY] = 11 + describe('when "Accept-Encoding: br"', function () { + it('when brotli is disabled should not compress', function (done) { + var server = createServer({ threshold: 0, encodings: { br: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - var server = createServer({ threshold: 0, brotli: { params: params } }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + request(server) + .get('/') + .set('Accept-Encoding', 'br') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'br') - .expect('Content-Encoding', 'br', done) + it('should respond with br', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'br') + .expect('Content-Encoding', 'br', done) + }) }) - it('shouldn\'t break compression when gzip is requested', function (done) { - var params = {} - params[zlib.constants.BROTLI_PARAM_QUALITY] = 8 + describe('when "Accept-Encoding: br" and passing compression level', function () { + it('should respond with br', function (done) { + var params = {} + params[zlib.constants.BROTLI_PARAM_QUALITY] = 11 - var server = createServer({ threshold: 0, brotli: { params: params } }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + var server = createServer({ threshold: 0, encodings: { br: { params: params } } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'br') + .expect('Content-Encoding', 'br', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip') - .expect('Content-Encoding', 'gzip', done) - }) - }) + it('shouldn\'t break compression when gzip is requested', function (done) { + var params = {} + params[zlib.constants.BROTLI_PARAM_QUALITY] = 8 - describe('when "Accept-Encoding: gzip, deflate"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') - }) + var server = createServer({ threshold: 0, encodings: { br: { params: params } } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip, deflate') - .expect('Content-Encoding', 'gzip', done) + request(server) + .get('/') + .set('Accept-Encoding', 'gzip') + .expect('Content-Encoding', 'gzip', done) + }) }) - }) - describe('when "Accept-Encoding: deflate, gzip"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: gzip, deflate"', function () { + it('should respond with deflate when gzip is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { gzip: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip, deflate') + .expect('Content-Encoding', 'deflate', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'deflate, gzip') - .expect('Content-Encoding', 'gzip', done) - }) - }) + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - describe('when "Accept-Encoding: gzip, br"', function () { - it('should respond with br', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + request(server) + .get('/') + .set('Accept-Encoding', 'gzip, deflate') + .expect('Content-Encoding', 'gzip', done) }) + }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip, br') - .expect('Content-Encoding', 'br', done) + describe('when "Accept-Encoding: deflate, gzip"', function () { + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, gzip') + .expect('Content-Encoding', 'gzip', done) + }) }) - it.skip('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: gzip, br"', function () { + it('should respond with gzip when brotli is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { br: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip, br') + .expect('Content-Encoding', 'gzip', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'br, gzip') - .expect('Content-Encoding', 'gzip', done) + it('should respond with br', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip, br') + .expect('Content-Encoding', 'br', done) + }) }) - }) - describe('when "Accept-Encoding: deflate, gzip, br"', function () { - it('should respond with br', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: deflate, gzip, br"', function () { + it('should respond with gzip when brotli is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { br: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, gzip, br') + .expect('Content-Encoding', 'gzip', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'deflate, gzip, br') - .expect('Content-Encoding', 'br', done) - }) - }) + it('should respond with deflate when brotli and gzip is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { br: false, gzip: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - describe('when "Accept-Encoding: gzip;q=1, br;q=0.3"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, gzip, br') + .expect('Content-Encoding', 'deflate', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip;q=1, br;q=0.3') - .expect('Content-Encoding', 'gzip', done) - }) - }) + it('should respond with br', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) - describe('when "Accept-Encoding: gzip, br;q=0.8"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, gzip, br') + .expect('Content-Encoding', 'br', done) }) + }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip, br;q=0.8') - .expect('Content-Encoding', 'gzip', done) + describe('when "Accept-Encoding: gzip;q=1, br;q=0.3"', function () { + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip;q=1, br;q=0.3') + .expect('Content-Encoding', 'gzip', done) + }) }) - }) - describe('when "Accept-Encoding: gzip;q=0.001"', function () { - it('should respond with gzip', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: gzip, br;q=0.8"', function () { + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip, br;q=0.8') + .expect('Content-Encoding', 'gzip', done) }) + }) - request(server) - .get('/') - .set('Accept-Encoding', 'gzip;q=0.001') - .expect('Content-Encoding', 'gzip', done) + describe('when "Accept-Encoding: gzip;q=0.001"', function () { + it('should respond with gzip', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'gzip;q=0.001') + .expect('Content-Encoding', 'gzip', done) + }) }) - }) - describe('when "Accept-Encoding: deflate, br"', function () { - it('should respond with br', function (done) { - var server = createServer({ threshold: 0 }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('when "Accept-Encoding: deflate, br"', function () { + it('should respond with deflate when brotli is disabled', function (done) { + var server = createServer({ threshold: 0, encodings: { br: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, br') + .expect('Content-Encoding', 'deflate', done) }) - request(server) - .get('/') - .set('Accept-Encoding', 'deflate, br') - .expect('Content-Encoding', 'br', done) + it('should respond with br', function (done) { + var server = createServer({ threshold: 0 }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', 'deflate, br') + .expect('Content-Encoding', 'br', done) + }) }) }) @@ -1000,43 +1102,88 @@ describe('compression()', function () { .expect(200, 'hello, world', done) }) - it('should compress when enforceEncoding is gzip', function (done) { - var server = createServer({ threshold: 0, enforceEncoding: 'gzip' }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('gzip', function () { + it('should compress when enforceEncoding is gzip', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'gzip' }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect('Content-Encoding', 'gzip') + .expect(200, 'hello, world', done) }) - request(server) - .get('/') - .set('Accept-Encoding', '') - .expect('Content-Encoding', 'gzip') - .expect(200, 'hello, world', done) + it('should skip when gzip is disabled', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'gzip', encodings: { gzip: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) + }) }) - it('should compress when enforceEncoding is deflate', function (done) { - var server = createServer({ threshold: 0, enforceEncoding: 'deflate' }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('deflate', function () { + it('should compress when enforceEncoding is deflate', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'deflate' }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect('Content-Encoding', 'deflate') + .expect(200, 'hello, world', done) }) - request(server) - .get('/') - .set('Accept-Encoding', '') - .expect('Content-Encoding', 'deflate') - .expect(200, 'hello, world', done) + it('should skip when deflate is disabled', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'deflate', encodings: { deflate: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) + }) }) - it('should compress when enforceEncoding is brotli', function (done) { - var server = createServer({ threshold: 0, enforceEncoding: 'br' }, function (req, res) { - res.setHeader('Content-Type', 'text/plain') - res.end('hello, world') + describe('brotli', function () { + it('should skip when brotli is disabled', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'br', encodings: { br: false } }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect(shouldNotHaveHeader('Content-Encoding')) + .expect(200, 'hello, world', done) }) - request(server) - .get('/') - .set('Accept-Encoding', '') - .expect('Content-Encoding', 'br') - .expect(200, done) + it('should compress when enforceEncoding is brotli', function (done) { + var server = createServer({ threshold: 0, enforceEncoding: 'br' }, function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.end('hello, world') + }) + + request(server) + .get('/') + .set('Accept-Encoding', '') + .expect('Content-Encoding', 'br') + .expect(200, done) + }) }) it('should not compress when enforceEncoding is unknown', function (done) {