Skip to content

Commit

Permalink
Merge 0597e85 into f72e0ba
Browse files Browse the repository at this point in the history
  • Loading branch information
SerayaEryn committed Feb 23, 2020
2 parents f72e0ba + 0597e85 commit f5ba030
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 39 deletions.
20 changes: 17 additions & 3 deletions README.md
Expand Up @@ -14,16 +14,30 @@ npm install encoding-negotiator
```js
const encodingNegotiator = require('encoding-negotiator');

encodingNegotiator.negotiate('compress;q=0.5, gzip;q=1.0', ['gzip', 'deflate', 'identity']); //returns gzip
encodingNegotiator.negotiate({
header: 'compress;q=0.5, gzip;q=1.0',
supportedEncodings: ['gzip', 'deflate', 'identity']
); //returns gzip
```
## API
### negotiate(header, supported)
Returns the most preffered encoding available in `supported` The first element of the `supported` array will be used in case of an asterisk.
Returns the most preffered encoding available in `supportedEncodings` The first
element of the `supportedEncodings` array will be used in case of an asterisk.
#### header
The `accept-encoding` header.
#### supported
#### supportedEncodings
An array of the supported encodings.
##### prefferedEncoding (optional)
An encoding preffered by the server if the client sends multiple encodings no
quality value (for example `Accept-Encoding: gzip, deflate, br`).
## Benchmark
```
Expand Down
6 changes: 3 additions & 3 deletions benchmark/benchmark.js
Expand Up @@ -12,15 +12,15 @@ const request = {
'accept-encoding': header
}
}
const availableEncodings = ['gzip', 'deflate', 'identity', 'br']
const supportedEncodings = ['gzip', 'deflate', 'identity', 'br']

suite
.add('negotiator', function () {
const negotiator = new Negotiator(request)
negotiator.encoding(availableEncodings)
negotiator.encoding(supportedEncodings)
})
.add('encoding-negotiator', function () {
encodingNegotiator.negotiate(header, availableEncodings)
encodingNegotiator.negotiate(header, supportedEncodings)
})
.on('cycle', function (event) {
console.log(String(event.target))
Expand Down
30 changes: 21 additions & 9 deletions index.js
@@ -1,33 +1,36 @@
'use strict'

function negotiate (header, supported) {
function negotiate (header, supportedEncodings) {
if (!header) {
return undefined
}
const supportedEncodings = createMap(supported)
const acceptedEncodings = parse(header || '')
.sort(comparator)
const supportedEncodingMap = createMap(supportedEncodings)
const acceptedEncodings = parse(header)
.sort((a, b) => comparator(a, b, supportedEncodingMap))
.filter(isNonZeroQuality)
return determinePreffered(acceptedEncodings, supportedEncodings)
return determinePreffered(acceptedEncodings, supportedEncodingMap)
}

function determinePreffered (acceptedEncodings, supportedEncodings) {
for (const encoding of acceptedEncodings) {
const selected = supportedEncodings[encoding.name]
if (selected) {
return selected
return selected.encoding
}
}
return null
}

function createMap (supported) {
const supportedEncodings = {}
let priority = 0
if (supported.length > 0) {
supportedEncodings['*'] = supported[0]
supportedEncodings['*'] = { encoding: supported[0], priority }
priority++
}
for (const encoding of supported) {
supportedEncodings[encoding] = encoding
supportedEncodings[encoding] = { encoding, priority }
priority++
}
return supportedEncodings
}
Expand Down Expand Up @@ -58,7 +61,16 @@ function getQuality (second) {
return parseFloat(quality)
}

function comparator (a, b) {
function comparator (a, b, supportedEncodingMap) {
if (a.quality === b.quality) {
if (supportedEncodingMap[a.name] &&
supportedEncodingMap[b.name] &&
supportedEncodingMap[a.name].priority < supportedEncodingMap[b.name].priority) {
return -1
} else {
return 1
}
}
return b.quality - a.quality
}

Expand Down
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -7,8 +7,7 @@
"unit": "ava test/*.js",
"test": "npm run lint && npm run unit",
"lint": "standard index.js test/* benchmark/*",
"coveralls": "nyc npm test",
"coverage-report": "nyc npm test && nyc report --reporter=html"
"coveralls": "nyc npm test"
},
"keywords": [
"encoding",
Expand Down
62 changes: 40 additions & 22 deletions test/test.js
Expand Up @@ -5,98 +5,116 @@ const enodingNegotiator = require('..')

test('should return identity', (t) => {
const header = 'identity;q=1'
const supported = ['gzip', 'identity']
const supportedEncodings = ['gzip', 'identity']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'identity')
})

test('should return gzip', (t) => {
const header = 'gzip;q=1, identity;q=0.5'
const supported = ['gzip', 'deflate']
const supportedEncodings = ['gzip', 'deflate']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'gzip')
})

test('should return deflate', (t) => {
const header = 'deflate;q=0.5,identity; q=0.5'
const supported = ['gzip', 'deflate']
const supportedEncodings = ['gzip', 'deflate']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'deflate')
})

test('"*" and ["gzip", "deflate"]', (t) => {
const header = '*'
const supported = ['gzip', 'deflate']
const supportedEncodings = ['gzip', 'deflate']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'gzip')
})

test('"deflate;q=1.0, *" and ["gzip"]', (t) => {
const header = 'deflate;q=1.0, *'
const supported = ['gzip']
const supportedEncodings = ['gzip']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'gzip')
})

test('should ignore invalid encoding if another valid encoding', (t) => {
const header = 'test,br'
const supported = ['br']
const supportedEncodings = ['br']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'br')
})

test('"gzip;q=0" and ["gzip"]', (t) => {
const header = 'gzip;q=0'
const supported = ['gzip', 'identity']
const supportedEncodings = ['gzip', 'identity']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, null)
})

test('unknown encoding', (t) => {
const header = 'white rabbit'
const supported = ['gzip', 'identity']
const supportedEncodings = ['gzip', 'identity']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, null)
})

test('return undefined if no header', (t) => {
const supported = ['gzip', 'identity']
const supportedEncodings = ['gzip', 'identity']

const result = enodingNegotiator.negotiate(undefined, supported)
const result = enodingNegotiator.negotiate(undefined, supportedEncodings)

t.is(result, undefined)
})

test('compress;q=0.5, gzip;q=1.0 and ["gzip", compress"]', (t) => {
const header = 'compress;q=0.5, gzip;q=1.0'
const supported = ['gzip', 'compress']
const supportedEncodings = ['gzip', 'compress']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'gzip')
})

test('compress;q=0.5, gzip;q=1.0 and ["compress"]', (t) => {
const header = 'compress;q=0.5, gzip;q=1.0'
const supported = ['compress']
const supportedEncodings = ['compress']

const result = enodingNegotiator.negotiate(header, supported)
const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'compress')
})

test('Should return "br" for "gzip, deflate, br" and ["br", "gzip", "deflate"]', (t) => {
const header = 'gzip, deflate, br'
const supportedEncodings = ['br', 'gzip', 'deflate']

const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'br')
})

test('Should return "br" for "*" and ["br", "gzip", "deflate"]', (t) => {
const header = '*'
const supportedEncodings = ['br', 'gzip', 'deflate']

const result = enodingNegotiator.negotiate(header, supportedEncodings)

t.is(result, 'br')
})

0 comments on commit f5ba030

Please sign in to comment.