You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.8 KiB

3 years ago
'use strict'
function negotiate (header, supportedEncodings) {
if (!header) {
return undefined
}
const supportedEncodingMap = createMap(supportedEncodings)
const acceptedEncodings = parse(header)
.sort((a, b) => comparator(a, b, supportedEncodingMap))
.filter(isNonZeroQuality)
return determinePreffered(acceptedEncodings, supportedEncodingMap)
}
function determinePreffered (acceptedEncodings, supportedEncodings) {
for (const encoding of acceptedEncodings) {
const selected = supportedEncodings[encoding.name]
if (selected) {
return selected.encoding
}
}
return null
}
function createMap (supported) {
const supportedEncodings = {}
let priority = 0
if (supported.length > 0) {
supportedEncodings['*'] = { encoding: supported[0], priority }
priority++
}
for (const encoding of supported) {
supportedEncodings[encoding] = { encoding, priority }
priority++
}
return supportedEncodings
}
function parse (header) {
const split = header.split(',')
return split.map(parseEncoding)
}
function isNonZeroQuality (encoding) {
return encoding.quality !== 0
}
function parseEncoding (encoding) {
const [name, second] = encoding.trim().split(';')
const quality = getQuality(second)
return {
name,
quality
}
}
function getQuality (second) {
if (!second) {
return 1
}
const [, quality] = second.trim().split('=')
return parseFloat(quality)
}
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
}
module.exports = {
negotiate
}