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