1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | 'use strict'
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | module.exports = etag
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | var crypto = require('crypto')
|
22 | var Stats = require('fs').Stats
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | var toString = Object.prototype.toString
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | function entitytag (entity) {
|
40 | if (entity.length === 0) {
|
41 |
|
42 | return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"'
|
43 | }
|
44 |
|
45 |
|
46 | var hash = crypto
|
47 | .createHash('sha1')
|
48 | .update(entity, 'utf8')
|
49 | .digest('base64')
|
50 | .substring(0, 27)
|
51 |
|
52 |
|
53 | var len = typeof entity === 'string'
|
54 | ? Buffer.byteLength(entity, 'utf8')
|
55 | : entity.length
|
56 |
|
57 | return '"' + len.toString(16) + '-' + hash + '"'
|
58 | }
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | function etag (entity, options) {
|
71 | if (entity == null) {
|
72 | throw new TypeError('argument entity is required')
|
73 | }
|
74 |
|
75 |
|
76 | var isStats = isstats(entity)
|
77 | var weak = options && typeof options.weak === 'boolean'
|
78 | ? options.weak
|
79 | : isStats
|
80 |
|
81 |
|
82 | if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
|
83 | throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
|
84 | }
|
85 |
|
86 |
|
87 | var tag = isStats
|
88 | ? stattag(entity)
|
89 | : entitytag(entity)
|
90 |
|
91 | return weak
|
92 | ? 'W/' + tag
|
93 | : tag
|
94 | }
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 | function isstats (obj) {
|
105 |
|
106 | if (typeof Stats === 'function' && obj instanceof Stats) {
|
107 | return true
|
108 | }
|
109 |
|
110 |
|
111 | return obj && typeof obj === 'object' &&
|
112 | 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' &&
|
113 | 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' &&
|
114 | 'ino' in obj && typeof obj.ino === 'number' &&
|
115 | 'size' in obj && typeof obj.size === 'number'
|
116 | }
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | function stattag (stat) {
|
127 | var mtime = stat.mtime.getTime().toString(16)
|
128 | var size = stat.size.toString(16)
|
129 |
|
130 | return '"' + size + '-' + mtime + '"'
|
131 | }
|