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.
|
|
/*! * 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*?(?:,|$)/
/** * 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 }
|