module.exports = preferredEncodings; preferredEncodings.preferredEncodings = preferredEncodings; function parseAcceptEncoding(accept) { var acceptableEncodings; if (accept) { acceptableEncodings = accept.split(',').map(function(e, i) { return parseEncoding(e.trim(), i); }); } else { acceptableEncodings = []; } if (!acceptableEncodings.some(function(e) { return e && specify('identity', e); })) { /* * If identity doesn't explicitly appear in the accept-encoding header, * it's added to the list of acceptable encoding with the lowest q * */ var lowestQ = 1; for(var i = 0; i < acceptableEncodings.length; i++){ var e = acceptableEncodings[i]; if(e && e.q < lowestQ){ lowestQ = e.q; } } acceptableEncodings.push({ encoding: 'identity', q: lowestQ / 2, }); } return acceptableEncodings.filter(function(e) { return e; }); } function parseEncoding(s, i) { var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/); if (!match) return null; var encoding = match[1]; var q = 1; if (match[2]) { var params = match[2].split(';'); for (var i = 0; i < params.length; i ++) { var p = params[i].trim().split('='); if (p[0] === 'q') { q = parseFloat(p[1]); break; } } } return { encoding: encoding, q: q, i: i }; } function getEncodingPriority(encoding, accepted) { return (accepted.map(function(a) { return specify(encoding, a); }).filter(Boolean).sort(function (a, b) { if(a.s == b.s) { return a.q > b.q ? -1 : 1; } else { return a.s > b.s ? -1 : 1; } })[0] || {s: 0, q: 0}); } function specify(encoding, spec) { var s = 0; if(spec.encoding.toLowerCase() === encoding.toLowerCase()){ s |= 1; } else if (spec.encoding !== '*' ) { return null } return { s: s, q: spec.q, } }; function preferredEncodings(accept, provided) { accept = parseAcceptEncoding(accept || ''); if (provided) { return provided.map(function(type) { return [type, getEncodingPriority(type, accept)]; }).filter(function(pair) { return pair[1].q > 0; }).sort(function(a, b) { var pa = a[1]; var pb = b[1]; return (pb.q - pa.q) || (pb.s - pa.s) || (pa.i - pb.i); }).map(function(pair) { return pair[0]; }); } else { return accept.sort(function (a, b) { // revsort return (b.q - a.q) || (a.i - b.i); }).filter(function(type){ return type.q > 0; }).map(function(type) { return type.encoding; }); } }