|
|
/**
|
|
* Expose `fresh()`.
|
|
*/
|
|
|
|
module.exports = fresh;
|
|
|
|
/**
|
|
* Check freshness of `req` and `res` headers.
|
|
*
|
|
* When the cache is "fresh" __true__ is returned,
|
|
* otherwise __false__ is returned to indicate that
|
|
* the cache is now stale.
|
|
*
|
|
* @param {Object} req
|
|
* @param {Object} res
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
|
|
function fresh(req, res) {
|
|
// defaults
|
|
var etagMatches = true;
|
|
var notModified = true;
|
|
|
|
// fields
|
|
var modifiedSince = req['if-modified-since'];
|
|
var noneMatch = req['if-none-match'];
|
|
var lastModified = res['last-modified'];
|
|
var etag = res['etag'];
|
|
var cc = req['cache-control'];
|
|
|
|
// unconditional request
|
|
if (!modifiedSince && !noneMatch) return false;
|
|
|
|
// check for no-cache cache request directive
|
|
if (cc && cc.indexOf('no-cache') !== -1) return false;
|
|
|
|
// parse if-none-match
|
|
if (noneMatch) noneMatch = noneMatch.split(/ *, */);
|
|
|
|
// if-none-match
|
|
if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0];
|
|
|
|
// if-modified-since
|
|
if (modifiedSince) {
|
|
modifiedSince = new Date(modifiedSince);
|
|
lastModified = new Date(lastModified);
|
|
notModified = lastModified <= modifiedSince;
|
|
}
|
|
|
|
return !! (etagMatches && notModified);
|
|
}
|