Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50650 views
1
/*!
2
* express
3
* Copyright(c) 2009-2013 TJ Holowaychuk
4
* Copyright(c) 2014-2015 Douglas Christopher Wilson
5
* MIT Licensed
6
*/
7
8
'use strict';
9
10
/**
11
* Module dependencies.
12
* @api private
13
*/
14
15
var contentDisposition = require('content-disposition');
16
var contentType = require('content-type');
17
var deprecate = require('depd')('express');
18
var flatten = require('array-flatten');
19
var mime = require('send').mime;
20
var basename = require('path').basename;
21
var etag = require('etag');
22
var proxyaddr = require('proxy-addr');
23
var qs = require('qs');
24
var querystring = require('querystring');
25
26
/**
27
* Return strong ETag for `body`.
28
*
29
* @param {String|Buffer} body
30
* @param {String} [encoding]
31
* @return {String}
32
* @api private
33
*/
34
35
exports.etag = function (body, encoding) {
36
var buf = !Buffer.isBuffer(body)
37
? new Buffer(body, encoding)
38
: body;
39
40
return etag(buf, {weak: false});
41
};
42
43
/**
44
* Return weak ETag for `body`.
45
*
46
* @param {String|Buffer} body
47
* @param {String} [encoding]
48
* @return {String}
49
* @api private
50
*/
51
52
exports.wetag = function wetag(body, encoding){
53
var buf = !Buffer.isBuffer(body)
54
? new Buffer(body, encoding)
55
: body;
56
57
return etag(buf, {weak: true});
58
};
59
60
/**
61
* Check if `path` looks absolute.
62
*
63
* @param {String} path
64
* @return {Boolean}
65
* @api private
66
*/
67
68
exports.isAbsolute = function(path){
69
if ('/' === path[0]) return true;
70
if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path
71
if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path
72
};
73
74
/**
75
* Flatten the given `arr`.
76
*
77
* @param {Array} arr
78
* @return {Array}
79
* @api private
80
*/
81
82
exports.flatten = deprecate.function(flatten,
83
'utils.flatten: use array-flatten npm module instead');
84
85
/**
86
* Normalize the given `type`, for example "html" becomes "text/html".
87
*
88
* @param {String} type
89
* @return {Object}
90
* @api private
91
*/
92
93
exports.normalizeType = function(type){
94
return ~type.indexOf('/')
95
? acceptParams(type)
96
: { value: mime.lookup(type), params: {} };
97
};
98
99
/**
100
* Normalize `types`, for example "html" becomes "text/html".
101
*
102
* @param {Array} types
103
* @return {Array}
104
* @api private
105
*/
106
107
exports.normalizeTypes = function(types){
108
var ret = [];
109
110
for (var i = 0; i < types.length; ++i) {
111
ret.push(exports.normalizeType(types[i]));
112
}
113
114
return ret;
115
};
116
117
/**
118
* Generate Content-Disposition header appropriate for the filename.
119
* non-ascii filenames are urlencoded and a filename* parameter is added
120
*
121
* @param {String} filename
122
* @return {String}
123
* @api private
124
*/
125
126
exports.contentDisposition = deprecate.function(contentDisposition,
127
'utils.contentDisposition: use content-disposition npm module instead');
128
129
/**
130
* Parse accept params `str` returning an
131
* object with `.value`, `.quality` and `.params`.
132
* also includes `.originalIndex` for stable sorting
133
*
134
* @param {String} str
135
* @return {Object}
136
* @api private
137
*/
138
139
function acceptParams(str, index) {
140
var parts = str.split(/ *; */);
141
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
142
143
for (var i = 1; i < parts.length; ++i) {
144
var pms = parts[i].split(/ *= */);
145
if ('q' === pms[0]) {
146
ret.quality = parseFloat(pms[1]);
147
} else {
148
ret.params[pms[0]] = pms[1];
149
}
150
}
151
152
return ret;
153
}
154
155
/**
156
* Compile "etag" value to function.
157
*
158
* @param {Boolean|String|Function} val
159
* @return {Function}
160
* @api private
161
*/
162
163
exports.compileETag = function(val) {
164
var fn;
165
166
if (typeof val === 'function') {
167
return val;
168
}
169
170
switch (val) {
171
case true:
172
fn = exports.wetag;
173
break;
174
case false:
175
break;
176
case 'strong':
177
fn = exports.etag;
178
break;
179
case 'weak':
180
fn = exports.wetag;
181
break;
182
default:
183
throw new TypeError('unknown value for etag function: ' + val);
184
}
185
186
return fn;
187
}
188
189
/**
190
* Compile "query parser" value to function.
191
*
192
* @param {String|Function} val
193
* @return {Function}
194
* @api private
195
*/
196
197
exports.compileQueryParser = function compileQueryParser(val) {
198
var fn;
199
200
if (typeof val === 'function') {
201
return val;
202
}
203
204
switch (val) {
205
case true:
206
fn = querystring.parse;
207
break;
208
case false:
209
fn = newObject;
210
break;
211
case 'extended':
212
fn = parseExtendedQueryString;
213
break;
214
case 'simple':
215
fn = querystring.parse;
216
break;
217
default:
218
throw new TypeError('unknown value for query parser function: ' + val);
219
}
220
221
return fn;
222
}
223
224
/**
225
* Compile "proxy trust" value to function.
226
*
227
* @param {Boolean|String|Number|Array|Function} val
228
* @return {Function}
229
* @api private
230
*/
231
232
exports.compileTrust = function(val) {
233
if (typeof val === 'function') return val;
234
235
if (val === true) {
236
// Support plain true/false
237
return function(){ return true };
238
}
239
240
if (typeof val === 'number') {
241
// Support trusting hop count
242
return function(a, i){ return i < val };
243
}
244
245
if (typeof val === 'string') {
246
// Support comma-separated values
247
val = val.split(/ *, */);
248
}
249
250
return proxyaddr.compile(val || []);
251
}
252
253
/**
254
* Set the charset in a given Content-Type string.
255
*
256
* @param {String} type
257
* @param {String} charset
258
* @return {String}
259
* @api private
260
*/
261
262
exports.setCharset = function setCharset(type, charset) {
263
if (!type || !charset) {
264
return type;
265
}
266
267
// parse type
268
var parsed = contentType.parse(type);
269
270
// set charset
271
parsed.parameters.charset = charset;
272
273
// format type
274
return contentType.format(parsed);
275
};
276
277
/**
278
* Parse an extended query string with qs.
279
*
280
* @return {Object}
281
* @private
282
*/
283
284
function parseExtendedQueryString(str) {
285
return qs.parse(str, {
286
allowPrototypes: true
287
});
288
}
289
290
/**
291
* Return new empty object.
292
*
293
* @return {Object}
294
* @api private
295
*/
296
297
function newObject() {
298
return {};
299
}
300
301