| |
| |
| |
| |
|
|
|
|
| 'use strict'
|
|
|
| |
| |
| |
|
|
|
|
| module.exports = etag
|
|
|
| |
| |
| |
|
|
|
|
| var crypto = require('crypto')
|
| var Stats = require('fs').Stats
|
|
|
| |
| |
| |
|
|
|
|
| var toString = Object.prototype.toString
|
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| function entitytag (entity) {
|
| if (entity.length === 0) {
|
|
|
| return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"'
|
| }
|
|
|
|
|
| var hash = crypto
|
| .createHash('sha1')
|
| .update(entity, 'utf8')
|
| .digest('base64')
|
| .substring(0, 27)
|
|
|
|
|
| var len = typeof entity === 'string'
|
| ? Buffer.byteLength(entity, 'utf8')
|
| : entity.length
|
|
|
| return '"' + len.toString(16) + '-' + hash + '"'
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| 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
|
|
|
|
|
| if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
|
| throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
|
| }
|
|
|
|
|
| var tag = isStats
|
| ? stattag(entity)
|
| : entitytag(entity)
|
|
|
| return weak
|
| ? 'W/' + tag
|
| : tag
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| function isstats (obj) {
|
|
|
| if (typeof Stats === 'function' && obj instanceof Stats) {
|
| return true
|
| }
|
|
|
|
|
| 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'
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
|
|
|
|
| function stattag (stat) {
|
| var mtime = stat.mtime.getTime().toString(16)
|
| var size = stat.size.toString(16)
|
|
|
| return '"' + size + '-' + mtime + '"'
|
| }
|
|
|