3 * Copyright(c) 2014 Douglas Christopher Wilson
11 module.exports = vary;
12 module.exports.append = append;
18 var separators = /[\(\)<>@,;:\\"\/\[\]\?=\{\}\u0020\u0009]/;
21 * Append a field to a vary header.
23 * @param {String} header
24 * @param {String|Array} field
29 function append(header, field) {
30 if (typeof header !== 'string') {
31 throw new TypeError('header argument is required');
35 throw new TypeError('field argument is required');
39 var fields = !Array.isArray(field)
40 ? parse(String(field))
43 // assert on invalid fields
44 for (var i = 0; i < fields.length; i++) {
45 if (separators.test(fields[i])) {
46 throw new TypeError('field argument contains an invalid header');
50 // existing, unspecified vary
55 // enumerate current values
56 var vals = parse(header.toLowerCase());
59 if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) {
63 for (var i = 0; i < fields.length; i++) {
64 field = fields[i].toLowerCase();
66 // append value (case-preserving)
67 if (vals.indexOf(field) === -1) {
70 ? header + ', ' + fields[i]
79 * Parse a vary header into an array.
81 * @param {String} header
86 function parse(header) {
87 return header.trim().split(/ *, */);
91 * Mark that a request is varied on a header field.
94 * @param {String|Array} field
98 function vary(res, field) {
99 if (!res || !res.getHeader || !res.setHeader) {
101 throw new TypeError('res argument is required');
104 // get existing header
105 var val = res.getHeader('Vary') || ''
106 var header = Array.isArray(val)
111 res.setHeader('Vary', append(header, field));