首先,这个属性是通过fresh来完成的(fresh用来判断req,res中的HTTP头是否依然有效),我们看看fresh是如何使用的:
var fresh = require('fresh') //引入fresh插件 var req = { 'if-none-match': 'tobi' }; var res = { 'etag': 'tobi' }; console.log(fresh(req, res));那么fresh内部是如何判断的呢:
var modifiedSince = req['if-modified-since']; var noneMatch = req['if-none-match']; //获取if-modified-since和if-none-match头,这是HTTP请求头 var lastModified = res['last-modified']; var etag = res['etag']; //获取last-modified和etag头,这是HTTP响应头 var cc = req['cache-control'];获取HTTP请求头if-modified-since和if-none-match,同时获取HTTP响应头last-modified和etag。然后还有获取请求头cache-control
if (!modifiedSince && !noneMatch) return false;如果HTTP请求头没有if-modified-since和if-none-match那么返回false(因为该fresh主要检查者两个头)
if (cc && cc.indexOf('no-cache') !== -1) return false;如果客户端发送了cache-control,同时cache-control为no-cache那么返回false,表示没有启用缓存,那么对HTTP请求头if-modified-since和if-none-match和HTTP响应头last-modified和etag的判断没有意义。
if (modifiedSince) { modifiedSince = new Date(modifiedSince); lastModified = new Date(lastModified); notModified = lastModified <= modifiedSince; }如果lastModified<modifiedSince那么表示服务器的资源没有发生改变,否则表示服务器端的资源已经被改变了!
if (noneMatch) noneMatch = noneMatch.split(/ *, */); //处理if-none-match头部 if (noneMatch) { etagMatches = noneMatch.some(function (match) { //如果if-none-match为*,或者和etag相同,或者和etag就相差了非单词字符,即“[^A-Za-z0-9_] return match === '*' || match === etag || match === 'W/' + etag; }); }最后的判断是否返回true/false如下:
return !! (etagMatches && notModified);也就是说:如果服务器端的资源没有发生改变(通过last-modified和if-modified-since来判断)的同时,而且满足以下任何一个条件,那么req,res中的HTTP头都是有效的:
.if-none-match的请求头为*
.if-none-match中保存的值和etag一致,表示数据没有发生改变
.if-none-match的请求头和etag请求头只是相差了一个w/!
总结:这个req.fresh是通过两对HTTP头,也就是if-none-match和etag,last-modified和if-modified-since来完成的。当然前提条件是启动了缓存,如果没有启动缓存那么就无所谓的请求头是否需要更新这一说!