http-header-list
Version:
Parser and logic functions for HTTP header lists
109 lines (90 loc) • 2.38 kB
JavaScript
/** @typedef {object} HeaderValue
*
* @property {string} value Option value
* @property {number} weight Weight of option
* @property {{[key: string]: string}} parameters Option parameters
*/
/** @constructor
* Create a parse header object that contains the parsed header
*
* @param {string} header Header value to parse
*/
export function HeaderList(header) {
if (typeof header !== 'string') {
throw new Error('headerValue should be a string');
}
/**
* The original header value
*/
this.header = header;
/** @type {HeaderValue[]}
* The parsed and sorted list of header values. The header values are
* sorted in descending order by the weight factor, q. If a header value
* does not have a weight factor, it will default to 1
*/
this.list;
if (!header) {
this.list = [];
return;
}
const headerParts = header.split(/ *, */);
const headerOptions = [];
for (let i = 0; i < headerParts.length; i++) {
const parts = headerParts[i].split(/ *; */);
const option = {
value: parts.shift(),
weight: 1,
parameters: {}
};
for (let j = 0; j < parts.length; j++) {
const parameters = parts[j].split(/ *= */);
if (parameters[0] === 'q') {
const weight = Number(parameters[1]);
if (!isNaN(weight)) {
option.weight = weight;
}
} else {
option.parameters[parameters[0]] = parameters[1];
}
}
headerOptions.push(option);
}
headerOptions.sort((a, b) => {
if (a.weight < b.weight) {
return 1;
}
if (a.weight > b.weight) {
return -1;
}
return 0;
});
this.list = headerOptions;
}
/**
* Find the first matching value that matches one of the values in the
* given array
*
* @param {string[]} possibleValues Possible values to match against
*/
HeaderList.prototype.firstMatch = function firstMatch(possibleValues) {
for (let i = 0; i < this.list.length; i++) {
if (possibleValues.indexOf(this.list[i].value) !== -1) {
return this.list[i];
}
}
};
/**
* Parse the given header and find the first matching value
*
* @param {string} header Header value to parse
* @param {string[]} possibleValues Possible values to match on
*
* @returns {HeaderValue} The first matching header value
*/
export const firstHeaderMatch = (header, possibleValues) => {
if (!header) {
return null;
}
const list = new HeaderList(header);
return list.firstMatch(possibleValues);
};