123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*!
- * etag
- * Copyright(c) 2014-2016 Douglas Christopher Wilson
- * MIT Licensed
- */
- 'use strict'
- /**
- * 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 + '"'
- }
|