Blame view

node_modules/etag/index.js 2.42 KB
ce4c83ff   wxy   初始提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  /*!
   * 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 + '"'
  }