UNPKG

express-static-gzip

Version:

simple wrapper on top of express.static, that allows serving pre-gziped files

106 lines (94 loc) 2.68 kB
// see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding // Indicates the identity function (i.e. no compression, nor modification) const IDENTITY = 'identity'; /** * * @param {string} acceptEncoding Content of the accept-encoding header * @param {{encodingName: string, fileExtension: string}[]} availableCompressions * @param {string[]} preference */ function findEncoding(acceptEncoding, availableCompressions, preference) { if (acceptEncoding) { let sortedEncodingList = parseEncoding(acceptEncoding); sortedEncodingList = takePreferenceIntoAccount( sortedEncodingList, preference ); return findFirstMatchingCompression( sortedEncodingList, availableCompressions ); } return null; } function findFirstMatchingCompression( sortedEncodingList, availableCompressions ) { for (const encoding of sortedEncodingList) { if (encoding === IDENTITY) { return null; } for (let availableCompression of availableCompressions) { if (encoding === '*' || encoding === availableCompression.encodingName) { return availableCompression; } } } return null; } /** * * @param {string[]} sortedEncodingList * @param {string[]} preferences */ function takePreferenceIntoAccount(sortedEncodingList, preferences) { if (!preferences || preferences.length === 0) { return sortedEncodingList; } for (let i = preferences.length - 1; i >= 0; i--) { let pref = preferences[i]; let matchIdx = sortedEncodingList.indexOf(pref); if (matchIdx >= 0) { sortedEncodingList.splice(matchIdx, 1); sortedEncodingList.splice(0, 0, pref); } } return sortedEncodingList; } /** * * @param {string} acceptedEncoding */ function parseEncoding(acceptedEncoding) { return acceptedEncoding .split(',') .map((encoding) => parseQuality(encoding)) .sort((encodingA, encodingB) => encodingB.q - encodingA.q) .filter((encoding) => encoding.q > 0) .map((encoding) => encoding.name); } /** * Parses the quality value of an entry. Empty value will be set to 1. * @param {string} encoding * @returns {{name: string, q: number}[]} */ function parseQuality(encoding) { let eSplit = encoding.split(';'); try { if (eSplit.length > 1) { const num = eSplit[1].trim().match(/q=(.*)/)[1]; return { name: eSplit[0].trim(), q: parseFloat(num), }; } } catch (ex) {} return { name: eSplit[0].trim(), q: 1, }; } module.exports = { findEncoding: findEncoding, };