| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 | /*! * vary * Copyright(c) 2014-2017 Douglas Christopher Wilson * MIT Licensed */'use strict'/** * Module exports. */module.exports = varymodule.exports.append = append/** * RegExp to match field-name in RFC 7230 sec 3.2 * * field-name    = token * token         = 1*tchar * tchar         = "!" / "#" / "$" / "%" / "&" / "'" / "*" *               / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" *               / DIGIT / ALPHA *               ; any VCHAR, except delimiters */var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$//** * Append a field to a vary header. * * @param {String} header * @param {String|Array} field * @return {String} * @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 field names  for (var j = 0; j < fields.length; j++) {    if (!FIELD_NAME_REGEXP.test(fields[j])) {      throw new TypeError('field argument contains an invalid header name')    }  }  // 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} * @private */function parse (header) {  var end = 0  var list = []  var start = 0  // gather tokens  for (var i = 0, len = header.length; i < len; i++) {    switch (header.charCodeAt(i)) {      case 0x20: /*   */        if (start === end) {          start = end = i + 1        }        break      case 0x2c: /* , */        list.push(header.substring(start, end))        start = end = i + 1        break      default:        end = i + 1        break    }  }  // final token  list.push(header.substring(start, end))  return list}/** * Mark that a request is varied on a header field. * * @param {Object} res * @param {String|Array} field * @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)  }}
 |