Mercurial > hg > nodescore
comparison node_modules/express/lib/utils.js @ 73:0c3a2942ddee
now using express to server static content
author | Rob Canning <rc@kiben.net> |
---|---|
date | Sun, 29 Jun 2014 12:11:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
72:9af4250ff7d5 | 73:0c3a2942ddee |
---|---|
1 /** | |
2 * Module dependencies. | |
3 */ | |
4 | |
5 var mime = require('send').mime; | |
6 var crc32 = require('buffer-crc32'); | |
7 var crypto = require('crypto'); | |
8 var basename = require('path').basename; | |
9 var deprecate = require('util').deprecate; | |
10 var proxyaddr = require('proxy-addr'); | |
11 | |
12 /** | |
13 * Simple detection of charset parameter in content-type | |
14 */ | |
15 var charsetRegExp = /;\s*charset\s*=/; | |
16 | |
17 /** | |
18 * Deprecate function, like core `util.deprecate`, | |
19 * but with NODE_ENV and color support. | |
20 * | |
21 * @param {Function} fn | |
22 * @param {String} msg | |
23 * @return {Function} | |
24 * @api private | |
25 */ | |
26 | |
27 exports.deprecate = function(fn, msg){ | |
28 if (process.env.NODE_ENV === 'test') return fn; | |
29 | |
30 // prepend module name | |
31 msg = 'express: ' + msg; | |
32 | |
33 if (process.stderr.isTTY) { | |
34 // colorize | |
35 msg = '\x1b[31;1m' + msg + '\x1b[0m'; | |
36 } | |
37 | |
38 return deprecate(fn, msg); | |
39 }; | |
40 | |
41 /** | |
42 * Return strong ETag for `body`. | |
43 * | |
44 * @param {String|Buffer} body | |
45 * @param {String} [encoding] | |
46 * @return {String} | |
47 * @api private | |
48 */ | |
49 | |
50 exports.etag = function etag(body, encoding){ | |
51 if (body.length === 0) { | |
52 // fast-path empty body | |
53 return '"1B2M2Y8AsgTpgAmY7PhCfg=="' | |
54 } | |
55 | |
56 var hash = crypto | |
57 .createHash('md5') | |
58 .update(body, encoding) | |
59 .digest('base64') | |
60 return '"' + hash + '"' | |
61 }; | |
62 | |
63 /** | |
64 * Return weak ETag for `body`. | |
65 * | |
66 * @param {String|Buffer} body | |
67 * @param {String} [encoding] | |
68 * @return {String} | |
69 * @api private | |
70 */ | |
71 | |
72 exports.wetag = function wetag(body, encoding){ | |
73 if (body.length === 0) { | |
74 // fast-path empty body | |
75 return 'W/"0-0"' | |
76 } | |
77 | |
78 var buf = Buffer.isBuffer(body) | |
79 ? body | |
80 : new Buffer(body, encoding) | |
81 var len = buf.length | |
82 return 'W/"' + len.toString(16) + '-' + crc32.unsigned(buf) + '"' | |
83 }; | |
84 | |
85 /** | |
86 * Check if `path` looks absolute. | |
87 * | |
88 * @param {String} path | |
89 * @return {Boolean} | |
90 * @api private | |
91 */ | |
92 | |
93 exports.isAbsolute = function(path){ | |
94 if ('/' == path[0]) return true; | |
95 if (':' == path[1] && '\\' == path[2]) return true; | |
96 if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path | |
97 }; | |
98 | |
99 /** | |
100 * Flatten the given `arr`. | |
101 * | |
102 * @param {Array} arr | |
103 * @return {Array} | |
104 * @api private | |
105 */ | |
106 | |
107 exports.flatten = function(arr, ret){ | |
108 ret = ret || []; | |
109 var len = arr.length; | |
110 for (var i = 0; i < len; ++i) { | |
111 if (Array.isArray(arr[i])) { | |
112 exports.flatten(arr[i], ret); | |
113 } else { | |
114 ret.push(arr[i]); | |
115 } | |
116 } | |
117 return ret; | |
118 }; | |
119 | |
120 /** | |
121 * Normalize the given `type`, for example "html" becomes "text/html". | |
122 * | |
123 * @param {String} type | |
124 * @return {Object} | |
125 * @api private | |
126 */ | |
127 | |
128 exports.normalizeType = function(type){ | |
129 return ~type.indexOf('/') | |
130 ? acceptParams(type) | |
131 : { value: mime.lookup(type), params: {} }; | |
132 }; | |
133 | |
134 /** | |
135 * Normalize `types`, for example "html" becomes "text/html". | |
136 * | |
137 * @param {Array} types | |
138 * @return {Array} | |
139 * @api private | |
140 */ | |
141 | |
142 exports.normalizeTypes = function(types){ | |
143 var ret = []; | |
144 | |
145 for (var i = 0; i < types.length; ++i) { | |
146 ret.push(exports.normalizeType(types[i])); | |
147 } | |
148 | |
149 return ret; | |
150 }; | |
151 | |
152 /** | |
153 * Generate Content-Disposition header appropriate for the filename. | |
154 * non-ascii filenames are urlencoded and a filename* parameter is added | |
155 * | |
156 * @param {String} filename | |
157 * @return {String} | |
158 * @api private | |
159 */ | |
160 | |
161 exports.contentDisposition = function(filename){ | |
162 var ret = 'attachment'; | |
163 if (filename) { | |
164 filename = basename(filename); | |
165 // if filename contains non-ascii characters, add a utf-8 version ala RFC 5987 | |
166 ret = /[^\040-\176]/.test(filename) | |
167 ? 'attachment; filename="' + encodeURI(filename) + '"; filename*=UTF-8\'\'' + encodeURI(filename) | |
168 : 'attachment; filename="' + filename + '"'; | |
169 } | |
170 | |
171 return ret; | |
172 }; | |
173 | |
174 /** | |
175 * Parse accept params `str` returning an | |
176 * object with `.value`, `.quality` and `.params`. | |
177 * also includes `.originalIndex` for stable sorting | |
178 * | |
179 * @param {String} str | |
180 * @return {Object} | |
181 * @api private | |
182 */ | |
183 | |
184 function acceptParams(str, index) { | |
185 var parts = str.split(/ *; */); | |
186 var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; | |
187 | |
188 for (var i = 1; i < parts.length; ++i) { | |
189 var pms = parts[i].split(/ *= */); | |
190 if ('q' == pms[0]) { | |
191 ret.quality = parseFloat(pms[1]); | |
192 } else { | |
193 ret.params[pms[0]] = pms[1]; | |
194 } | |
195 } | |
196 | |
197 return ret; | |
198 } | |
199 | |
200 /** | |
201 * Compile "etag" value to function. | |
202 * | |
203 * @param {Boolean|String|Function} val | |
204 * @return {Function} | |
205 * @api private | |
206 */ | |
207 | |
208 exports.compileETag = function(val) { | |
209 var fn; | |
210 | |
211 if (typeof val === 'function') { | |
212 return val; | |
213 } | |
214 | |
215 switch (val) { | |
216 case true: | |
217 fn = exports.wetag; | |
218 break; | |
219 case false: | |
220 break; | |
221 case 'strong': | |
222 fn = exports.etag; | |
223 break; | |
224 case 'weak': | |
225 fn = exports.wetag; | |
226 break; | |
227 default: | |
228 throw new TypeError('unknown value for etag function: ' + val); | |
229 } | |
230 | |
231 return fn; | |
232 } | |
233 | |
234 /** | |
235 * Compile "proxy trust" value to function. | |
236 * | |
237 * @param {Boolean|String|Number|Array|Function} val | |
238 * @return {Function} | |
239 * @api private | |
240 */ | |
241 | |
242 exports.compileTrust = function(val) { | |
243 if (typeof val === 'function') return val; | |
244 | |
245 if (val === true) { | |
246 // Support plain true/false | |
247 return function(){ return true }; | |
248 } | |
249 | |
250 if (typeof val === 'number') { | |
251 // Support trusting hop count | |
252 return function(a, i){ return i < val }; | |
253 } | |
254 | |
255 if (typeof val === 'string') { | |
256 // Support comma-separated values | |
257 val = val.split(/ *, */); | |
258 } | |
259 | |
260 return proxyaddr.compile(val || []); | |
261 } | |
262 | |
263 /** | |
264 * Set the charset in a given Content-Type string. | |
265 * | |
266 * @param {String} type | |
267 * @param {String} charset | |
268 * @return {String} | |
269 * @api private | |
270 */ | |
271 | |
272 exports.setCharset = function(type, charset){ | |
273 if (!type || !charset) return type; | |
274 | |
275 var exists = charsetRegExp.test(type); | |
276 | |
277 // removing existing charset | |
278 if (exists) { | |
279 var parts = type.split(';'); | |
280 | |
281 for (var i = 1; i < parts.length; i++) { | |
282 if (charsetRegExp.test(';' + parts[i])) { | |
283 parts.splice(i, 1); | |
284 break; | |
285 } | |
286 } | |
287 | |
288 type = parts.join(';'); | |
289 } | |
290 | |
291 return type + '; charset=' + charset; | |
292 }; |