Skip to content

Commit

Permalink
implemented required encoding negotiator without 3rd party dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgindi committed Dec 19, 2020
1 parent 04ab713 commit b024cce
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 106 deletions.
78 changes: 78 additions & 0 deletions encoding_negotiator.js
@@ -0,0 +1,78 @@
var zlib = require('zlib')

/**
* @const
* whether current node version has brotli support
*/
var hasBrotliSupport = 'createBrotliCompress' in zlib

var supportedEncodings = hasBrotliSupport
? ['br', 'gzip', 'deflate', 'identity']
: ['gzip', 'deflate', 'identity']

var preferredEncodings = hasBrotliSupport
? ['br', 'gzip']
: ['gzip']

function negotiateEncoding (header) {
header = header || ''

var insts = header.split(',')
var decoded = []

for (var i = 0; i < insts.length; i++) {
var inst = insts[i].match(/^\s*?([^\s;]+?)\s*?(?:;(.*))?$/)
if (!inst) continue

var encoding = inst[1]
if (supportedEncodings.indexOf(encoding) === -1) {
continue
}

var q = 1
if (inst[2]) {
var params = inst[2].split(';')
for (var j = 0; j < params.length; j++) {
var p = params[j].trim().split('=')
if (p[0] === 'q') {
q = parseFloat(p[1])
break
}
}
}

if (q < 0 || q > 1) { // invalid
continue
}

decoded.push({ encoding: encoding, q: q, i: i })
}

decoded.sort((a, b) => {
if (a.q !== b.q) {
return b.q - a.q // higher quality first
}

var aPreferred = preferredEncodings.indexOf(a.encoding)
var bPreferred = preferredEncodings.indexOf(b.encoding)

if (aPreferred === -1 && bPreferred === -1) {
return a.i - b.i // consider the original order
}

if (aPreferred !== -1 && bPreferred !== -1) {
return aPreferred - bPreferred // consider the preferred order
}

return aPreferred === -1 ? 1 : -1 // preferred first
})

if (decoded.length > 0) {
return decoded[0].encoding
}

return null
}

module.exports.hasBrotliSupport = hasBrotliSupport
module.exports.negotiateEncoding = negotiateEncoding
12 changes: 5 additions & 7 deletions index.js
Expand Up @@ -22,8 +22,8 @@ var objectAssign = require('object-assign')
var onHeaders = require('on-headers')
var vary = require('vary')
var zlib = require('zlib')

var Encodings = require('./lib/encodings')
var hasBrotliSupport = require('./encoding_negotiator').hasBrotliSupport
var negotiateEncoding = require('./encoding_negotiator').negotiateEncoding

/**
* Module exports.
Expand All @@ -50,7 +50,7 @@ var cacheControlNoTransformRegExp = /(?:^|,)\s*?no-transform\s*?(?:,|$)/
function compression (options) {
var opts = options || {}

if (Encodings.hasBrotliSupport) {
if (hasBrotliSupport) {
// set the default level to a reasonable value with balanced speed/ratio
if (opts.params === undefined) {
opts = objectAssign({}, opts)
Expand Down Expand Up @@ -189,12 +189,10 @@ function compression (options) {
}

// compression method
var encodings = new Encodings()
encodings.parseAcceptEncoding(req.headers['accept-encoding'] || 'identity')
var method = encodings.getPreferredContentEncoding()
var method = negotiateEncoding(req.headers['accept-encoding']) || 'identity'

// negotiation failed
if (!method || method === 'identity') {
if (method === 'identity') {
nocompress('not acceptable')
return
}
Expand Down
98 changes: 0 additions & 98 deletions lib/encodings.js

This file was deleted.

1 change: 0 additions & 1 deletion package.json
Expand Up @@ -9,7 +9,6 @@
"license": "MIT",
"repository": "expressjs/compression",
"dependencies": {
"accepts": "~1.3.7",
"bytes": "3.0.0",
"compressible": "~2.0.17",
"debug": "2.6.9",
Expand Down

0 comments on commit b024cce

Please sign in to comment.