Spaces:
Build error
Build error
| /*! | |
| * fresh | |
| * Copyright(c) 2012 TJ Holowaychuk | |
| * Copyright(c) 2016-2017 Douglas Christopher Wilson | |
| * MIT Licensed | |
| */ | |
| /** | |
| * RegExp to check for no-cache token in Cache-Control. | |
| * @private | |
| */ | |
| var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/ | |
| /** | |
| * Module exports. | |
| * @public | |
| */ | |
| module.exports = fresh | |
| /** | |
| * Check freshness of the response using request and response headers. | |
| * | |
| * @param {Object} reqHeaders | |
| * @param {Object} resHeaders | |
| * @return {Boolean} | |
| * @public | |
| */ | |
| function fresh (reqHeaders, resHeaders) { | |
| // fields | |
| var modifiedSince = reqHeaders['if-modified-since'] | |
| var noneMatch = reqHeaders['if-none-match'] | |
| // unconditional request | |
| if (!modifiedSince && !noneMatch) { | |
| return false | |
| } | |
| // Always return stale when Cache-Control: no-cache | |
| // to support end-to-end reload requests | |
| // https://tools.ietf.org/html/rfc2616#section-14.9.4 | |
| var cacheControl = reqHeaders['cache-control'] | |
| if (cacheControl && CACHE_CONTROL_NO_CACHE_REGEXP.test(cacheControl)) { | |
| return false | |
| } | |
| // if-none-match | |
| if (noneMatch && noneMatch !== '*') { | |
| var etag = resHeaders['etag'] | |
| if (!etag) { | |
| return false | |
| } | |
| var etagStale = true | |
| var matches = parseTokenList(noneMatch) | |
| for (var i = 0; i < matches.length; i++) { | |
| var match = matches[i] | |
| if (match === etag || match === 'W/' + etag || 'W/' + match === etag) { | |
| etagStale = false | |
| break | |
| } | |
| } | |
| if (etagStale) { | |
| return false | |
| } | |
| } | |
| // if-modified-since | |
| if (modifiedSince) { | |
| var lastModified = resHeaders['last-modified'] | |
| var modifiedStale = !lastModified || !(parseHttpDate(lastModified) <= parseHttpDate(modifiedSince)) | |
| if (modifiedStale) { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| /** | |
| * Parse an HTTP Date into a number. | |
| * | |
| * @param {string} date | |
| * @private | |
| */ | |
| function parseHttpDate (date) { | |
| var timestamp = date && Date.parse(date) | |
| // istanbul ignore next: guard against date.js Date.parse patching | |
| return typeof timestamp === 'number' | |
| ? timestamp | |
| : NaN | |
| } | |
| /** | |
| * Parse a HTTP token list. | |
| * | |
| * @param {string} str | |
| * @private | |
| */ | |
| function parseTokenList (str) { | |
| var end = 0 | |
| var list = [] | |
| var start = 0 | |
| // gather tokens | |
| for (var i = 0, len = str.length; i < len; i++) { | |
| switch (str.charCodeAt(i)) { | |
| case 0x20: /* */ | |
| if (start === end) { | |
| start = end = i + 1 | |
| } | |
| break | |
| case 0x2c: /* , */ | |
| list.push(str.substring(start, end)) | |
| start = end = i + 1 | |
| break | |
| default: | |
| end = i + 1 | |
| break | |
| } | |
| } | |
| // final token | |
| list.push(str.substring(start, end)) | |
| return list | |
| } | |