/*! * fresh * Copyright(c) 2012 TJ Holowaychuk * Copyright(c) 2016-2017 Douglas Christopher Wilson * MIT Licensed */ 'use strict' /** * RegExp to check for no-cache token in Cache-Control. * @private */ var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/ /** * Simple expression to split token list. * @private */ var TOKEN_LIST_REGEXP = / *, */ /** * 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'] var etagStale = !etag || noneMatch.split(TOKEN_LIST_REGEXP).every(function (match) { return match !== etag && match !== 'W/' + etag && 'W/' + match !== etag }) if (etagStale) { return false } } // if-modified-since if (modifiedSince) { var lastModified = resHeaders['last-modified'] var modifiedStale = !lastModified || Date.parse(lastModified) > Date.parse(modifiedSince) if (modifiedStale) { return false } } return true }