diff options
Diffstat (limited to 'dgbuilder/dgeflows/node_modules/express/node_modules/etag/index.js')
-rw-r--r-- | dgbuilder/dgeflows/node_modules/express/node_modules/etag/index.js | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/dgbuilder/dgeflows/node_modules/express/node_modules/etag/index.js b/dgbuilder/dgeflows/node_modules/express/node_modules/etag/index.js new file mode 100644 index 00000000..bb05eb7e --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/node_modules/etag/index.js @@ -0,0 +1,171 @@ +/*! + * etag + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * Module exports. + */ + +module.exports = etag + +/** + * Module dependencies. + */ + +var crc = require('crc').crc32 +var crypto = require('crypto') +var Stats = require('fs').Stats + +/** + * Module variables. + */ + +var crc32threshold = 1000 // 1KB +var NULL = new Buffer([0]) +var toString = Object.prototype.toString + +/** + * Create a simple ETag. + * + * @param {string|Buffer|Stats} entity + * @param {object} [options] + * @param {boolean} [options.weak] + * @return {String} + * @api public + */ + +function etag(entity, options) { + if (entity == null) { + throw new TypeError('argument entity is required') + } + + var isStats = isstats(entity) + var weak = options && typeof options.weak === 'boolean' + ? options.weak + : isStats + + // support fs.Stats object + if (isStats) { + return stattag(entity, weak) + } + + if (typeof entity !== 'string' && !Buffer.isBuffer(entity)) { + throw new TypeError('argument entity must be string, Buffer, or fs.Stats') + } + + var hash = weak + ? weakhash(entity) + : stronghash(entity) + + return weak + ? 'W/"' + hash + '"' + : '"' + hash + '"' +} + +/** + * Determine if object is a Stats object. + * + * @param {object} obj + * @return {boolean} + * @api private + */ + +function isstats(obj) { + // not even an object + if (obj === null || typeof obj !== 'object') { + return false + } + + // genuine fs.Stats + if (obj instanceof Stats) { + return true + } + + // quack quack + return 'atime' in obj && toString.call(obj.atime) === '[object Date]' + && '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 {Buffer} entity + * @return {String} + * @api private + */ + +function stattag(stat, weak) { + var mtime = stat.mtime.toISOString() + var size = stat.size.toString(16) + + if (weak) { + return 'W/"' + size + '-' + crc(mtime) + '"' + } + + var hash = crypto + .createHash('md5') + .update('file', 'utf8') + .update(NULL) + .update(size, 'utf8') + .update(NULL) + .update(mtime, 'utf8') + .digest('base64') + + return '"' + hash + '"' +} + +/** + * Generate a strong hash. + * + * @param {Buffer} entity + * @return {String} + * @api private + */ + +function stronghash(entity) { + if (entity.length === 0) { + // fast-path empty + return '1B2M2Y8AsgTpgAmY7PhCfg==' + } + + return crypto + .createHash('md5') + .update(entity, 'utf8') + .digest('base64') +} + +/** + * Generate a weak hash. + * + * @param {Buffer} entity + * @return {String} + * @api private + */ + +function weakhash(entity) { + if (entity.length === 0) { + // fast-path empty + return '0-0' + } + + var len = typeof entity === 'string' + ? Buffer.byteLength(entity, 'utf8') + : entity.length + + if (len <= crc32threshold) { + // crc32 plus length when it's fast + // crc(str) only accepts utf-8 encoding + return len.toString(16) + '-' + crc(entity).toString(16) + } + + // use md4 for long strings + return crypto + .createHash('md4') + .update(entity, 'utf8') + .digest('base64') +} |