|
|
/*! * vary * Copyright(c) 2014-2015 Douglas Christopher Wilson * MIT Licensed */
'use strict';
/** * Module exports. */
module.exports = vary; module.exports.append = append;
/** * Variables. */
var separators = /[\(\)<>@,;:\\"\/\[\]\?=\{\}\u0020\u0009]/;
/** * Append a field to a vary header. * * @param {String} header * @param {String|Array} field * @return {String} * @api public */
function append(header, field) { if (typeof header !== 'string') { throw new TypeError('header argument is required'); }
if (!field) { throw new TypeError('field argument is required'); }
// get fields array
var fields = !Array.isArray(field) ? parse(String(field)) : field;
// assert on invalid fields
for (var i = 0; i < fields.length; i++) { if (separators.test(fields[i])) { throw new TypeError('field argument contains an invalid header'); } }
// existing, unspecified vary
if (header === '*') { return header; }
// enumerate current values
var val = header; var vals = parse(header.toLowerCase());
// unspecified vary
if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) { return '*'; }
for (var i = 0; i < fields.length; i++) { var fld = fields[i].toLowerCase();
// append value (case-preserving)
if (vals.indexOf(fld) === -1) { vals.push(fld); val = val ? val + ', ' + fields[i] : fields[i]; } }
return val; }
/** * Parse a vary header into an array. * * @param {String} header * @return {Array} * @api private */
function parse(header) { return header.trim().split(/ *, */); }
/** * Mark that a request is varied on a header field. * * @param {Object} res * @param {String|Array} field * @api public */
function vary(res, field) { if (!res || !res.getHeader || !res.setHeader) { // quack quack
throw new TypeError('res argument is required'); }
// get existing header
var val = res.getHeader('Vary') || '' var header = Array.isArray(val) ? val.join(', ') : String(val);
// set new header
if ((val = append(header, field))) { res.setHeader('Vary', val); } }
|