Spaces:
Sleeping
Sleeping
/*! | |
* etag | |
* Copyright(c) 2014-2016 Douglas Christopher Wilson | |
* MIT Licensed | |
*/ | |
/** | |
* Module exports. | |
* @public | |
*/ | |
module.exports = etag | |
/** | |
* Module dependencies. | |
* @private | |
*/ | |
var crypto = require('crypto') | |
var Stats = require('fs').Stats | |
/** | |
* Module variables. | |
* @private | |
*/ | |
var toString = Object.prototype.toString | |
/** | |
* Generate an entity tag. | |
* | |
* @param {Buffer|string} entity | |
* @return {string} | |
* @private | |
*/ | |
function entitytag (entity) { | |
if (entity.length === 0) { | |
// fast-path empty | |
return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"' | |
} | |
// compute hash of entity | |
var hash = crypto | |
.createHash('sha1') | |
.update(entity, 'utf8') | |
.digest('base64') | |
.substring(0, 27) | |
// compute length of entity | |
var len = typeof entity === 'string' | |
? Buffer.byteLength(entity, 'utf8') | |
: entity.length | |
return '"' + len.toString(16) + '-' + hash + '"' | |
} | |
/** | |
* Create a simple ETag. | |
* | |
* @param {string|Buffer|Stats} entity | |
* @param {object} [options] | |
* @param {boolean} [options.weak] | |
* @return {String} | |
* @public | |
*/ | |
function etag (entity, options) { | |
if (entity == null) { | |
throw new TypeError('argument entity is required') | |
} | |
// support fs.Stats object | |
var isStats = isstats(entity) | |
var weak = options && typeof options.weak === 'boolean' | |
? options.weak | |
: isStats | |
// validate argument | |
if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) { | |
throw new TypeError('argument entity must be string, Buffer, or fs.Stats') | |
} | |
// generate entity tag | |
var tag = isStats | |
? stattag(entity) | |
: entitytag(entity) | |
return weak | |
? 'W/' + tag | |
: tag | |
} | |
/** | |
* Determine if object is a Stats object. | |
* | |
* @param {object} obj | |
* @return {boolean} | |
* @api private | |
*/ | |
function isstats (obj) { | |
// genuine fs.Stats | |
if (typeof Stats === 'function' && obj instanceof Stats) { | |
return true | |
} | |
// quack quack | |
return obj && typeof obj === 'object' && | |
'ctime' in obj && toString.call(obj.ctime) === '[object Date]' && | |
'mtime' in obj && toString.call(obj.mtime) === '[object Date]' && | |
'ino' in obj && typeof obj.ino === 'number' && | |
'size' in obj && typeof obj.size === 'number' | |
} | |
/** | |
* Generate a tag for a stat. | |
* | |
* @param {object} stat | |
* @return {string} | |
* @private | |
*/ | |
function stattag (stat) { | |
var mtime = stat.mtime.getTime().toString(16) | |
var size = stat.size.toString(16) | |
return '"' + size + '-' + mtime + '"' | |
} | |