The LM Control website. Simple yet efficient.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.js 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*!
  2. * fresh
  3. * Copyright(c) 2012 TJ Holowaychuk
  4. * Copyright(c) 2016-2017 Douglas Christopher Wilson
  5. * MIT Licensed
  6. */
  7. 'use strict'
  8. /**
  9. * RegExp to check for no-cache token in Cache-Control.
  10. * @private
  11. */
  12. var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/
  13. /**
  14. * Module exports.
  15. * @public
  16. */
  17. module.exports = fresh
  18. /**
  19. * Check freshness of the response using request and response headers.
  20. *
  21. * @param {Object} reqHeaders
  22. * @param {Object} resHeaders
  23. * @return {Boolean}
  24. * @public
  25. */
  26. function fresh (reqHeaders, resHeaders) {
  27. // fields
  28. var modifiedSince = reqHeaders['if-modified-since']
  29. var noneMatch = reqHeaders['if-none-match']
  30. // unconditional request
  31. if (!modifiedSince && !noneMatch) {
  32. return false
  33. }
  34. // Always return stale when Cache-Control: no-cache
  35. // to support end-to-end reload requests
  36. // https://tools.ietf.org/html/rfc2616#section-14.9.4
  37. var cacheControl = reqHeaders['cache-control']
  38. if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) {
  39. return false
  40. }
  41. // if-none-match
  42. if (noneMatch && noneMatch !== '*') {
  43. var etag = resHeaders['etag']
  44. if (!etag) {
  45. return false
  46. }
  47. var etagStale = true
  48. var matches = parseTokenList(noneMatch)
  49. for (var i = 0; i < matches.length; i++) {
  50. var match = matches[i]
  51. if (match === etag || match === 'W/' + etag || 'W/' + match === etag) {
  52. etagStale = false
  53. break
  54. }
  55. }
  56. if (etagStale) {
  57. return false
  58. }
  59. }
  60. // if-modified-since
  61. if (modifiedSince) {
  62. var lastModified = resHeaders['last-modified']
  63. var modifiedStale = !lastModified || !(parseHttpDate(lastModified) <= parseHttpDate(modifiedSince))
  64. if (modifiedStale) {
  65. return false
  66. }
  67. }
  68. return true
  69. }
  70. /**
  71. * Parse an HTTP Date into a number.
  72. *
  73. * @param {string} date
  74. * @private
  75. */
  76. function parseHttpDate (date) {
  77. var timestamp = date && Date.parse(date)
  78. // istanbul ignore next: guard against date.js Date.parse patching
  79. return typeof timestamp === 'number'
  80. ? timestamp
  81. : NaN
  82. }
  83. /**
  84. * Parse a HTTP token list.
  85. *
  86. * @param {string} str
  87. * @private
  88. */
  89. function parseTokenList (str) {
  90. var end = 0
  91. var list = []
  92. var start = 0
  93. // gather tokens
  94. for (var i = 0, len = str.length; i < len; i++) {
  95. switch (str.charCodeAt(i)) {
  96. case 0x20: /* */
  97. if (start === end) {
  98. start = end = i + 1
  99. }
  100. break
  101. case 0x2c: /* , */
  102. list.push(str.substring(start, end))
  103. start = end = i + 1
  104. break
  105. default:
  106. end = i + 1
  107. break
  108. }
  109. }
  110. // final token
  111. list.push(str.substring(start, end))
  112. return list
  113. }