You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.1 KiB

8 years ago
  1. /*!
  2. * vary
  3. * Copyright(c) 2014-2015 Douglas Christopher Wilson
  4. * MIT Licensed
  5. */
  6. 'use strict';
  7. /**
  8. * Module exports.
  9. */
  10. module.exports = vary;
  11. module.exports.append = append;
  12. /**
  13. * Variables.
  14. */
  15. var separators = /[\(\)<>@,;:\\"\/\[\]\?=\{\}\u0020\u0009]/;
  16. /**
  17. * Append a field to a vary header.
  18. *
  19. * @param {String} header
  20. * @param {String|Array} field
  21. * @return {String}
  22. * @api public
  23. */
  24. function append(header, field) {
  25. if (typeof header !== 'string') {
  26. throw new TypeError('header argument is required');
  27. }
  28. if (!field) {
  29. throw new TypeError('field argument is required');
  30. }
  31. // get fields array
  32. var fields = !Array.isArray(field)
  33. ? parse(String(field))
  34. : field;
  35. // assert on invalid fields
  36. for (var i = 0; i < fields.length; i++) {
  37. if (separators.test(fields[i])) {
  38. throw new TypeError('field argument contains an invalid header');
  39. }
  40. }
  41. // existing, unspecified vary
  42. if (header === '*') {
  43. return header;
  44. }
  45. // enumerate current values
  46. var val = header;
  47. var vals = parse(header.toLowerCase());
  48. // unspecified vary
  49. if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) {
  50. return '*';
  51. }
  52. for (var i = 0; i < fields.length; i++) {
  53. var fld = fields[i].toLowerCase();
  54. // append value (case-preserving)
  55. if (vals.indexOf(fld) === -1) {
  56. vals.push(fld);
  57. val = val
  58. ? val + ', ' + fields[i]
  59. : fields[i];
  60. }
  61. }
  62. return val;
  63. }
  64. /**
  65. * Parse a vary header into an array.
  66. *
  67. * @param {String} header
  68. * @return {Array}
  69. * @api private
  70. */
  71. function parse(header) {
  72. return header.trim().split(/ *, */);
  73. }
  74. /**
  75. * Mark that a request is varied on a header field.
  76. *
  77. * @param {Object} res
  78. * @param {String|Array} field
  79. * @api public
  80. */
  81. function vary(res, field) {
  82. if (!res || !res.getHeader || !res.setHeader) {
  83. // quack quack
  84. throw new TypeError('res argument is required');
  85. }
  86. // get existing header
  87. var val = res.getHeader('Vary') || ''
  88. var header = Array.isArray(val)
  89. ? val.join(', ')
  90. : String(val);
  91. // set new header
  92. if ((val = append(header, field))) {
  93. res.setHeader('Vary', val);
  94. }
  95. }