| /*! |
| * 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); |
| } |
| } |