@mila.solutions/express 5.2.1-mila.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/express.js ADDED
@@ -0,0 +1,81 @@
1
+ /*!
2
+ * express
3
+ * Copyright(c) 2009-2013 TJ Holowaychuk
4
+ * Copyright(c) 2013 Roman Shtylman
5
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
6
+ * MIT Licensed
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * Module dependencies.
13
+ */
14
+
15
+ var bodyParser = require('body-parser')
16
+ var EventEmitter = require('node:events').EventEmitter;
17
+ var mixin = require('merge-descriptors');
18
+ var proto = require('./application');
19
+ var Router = require('router');
20
+ var req = require('./request');
21
+ var res = require('./response');
22
+
23
+ /**
24
+ * Expose `createApplication()`.
25
+ */
26
+
27
+ exports = module.exports = createApplication;
28
+
29
+ /**
30
+ * Create an express application.
31
+ *
32
+ * @return {Function}
33
+ * @api public
34
+ */
35
+
36
+ function createApplication() {
37
+ var app = function(req, res, next) {
38
+ app.handle(req, res, next);
39
+ };
40
+
41
+ mixin(app, EventEmitter.prototype, false);
42
+ mixin(app, proto, false);
43
+
44
+ // expose the prototype that will get set on requests
45
+ app.request = Object.create(req, {
46
+ app: { configurable: true, enumerable: true, writable: true, value: app }
47
+ })
48
+
49
+ // expose the prototype that will get set on responses
50
+ app.response = Object.create(res, {
51
+ app: { configurable: true, enumerable: true, writable: true, value: app }
52
+ })
53
+
54
+ app.init();
55
+ return app;
56
+ }
57
+
58
+ /**
59
+ * Expose the prototypes.
60
+ */
61
+
62
+ exports.application = proto;
63
+ exports.request = req;
64
+ exports.response = res;
65
+
66
+ /**
67
+ * Expose constructors.
68
+ */
69
+
70
+ exports.Route = Router.Route;
71
+ exports.Router = Router;
72
+
73
+ /**
74
+ * Expose middleware
75
+ */
76
+
77
+ exports.json = bodyParser.json
78
+ exports.raw = bodyParser.raw
79
+ exports.static = require('serve-static');
80
+ exports.text = bodyParser.text
81
+ exports.urlencoded = bodyParser.urlencoded
package/lib/request.js ADDED
@@ -0,0 +1,527 @@
1
+ /*!
2
+ * express
3
+ * Copyright(c) 2009-2013 TJ Holowaychuk
4
+ * Copyright(c) 2013 Roman Shtylman
5
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
6
+ * MIT Licensed
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * Module dependencies.
13
+ * @private
14
+ */
15
+
16
+ var accepts = require('accepts');
17
+ var isIP = require('node:net').isIP;
18
+ var typeis = require('type-is');
19
+ var http = require('node:http');
20
+ var fresh = require('fresh');
21
+ var parseRange = require('range-parser');
22
+ var parse = require('parseurl');
23
+ var proxyaddr = require('proxy-addr');
24
+
25
+ /**
26
+ * Request prototype.
27
+ * @public
28
+ */
29
+
30
+ var req = Object.create(http.IncomingMessage.prototype)
31
+
32
+ /**
33
+ * Module exports.
34
+ * @public
35
+ */
36
+
37
+ module.exports = req
38
+
39
+ /**
40
+ * Return request header.
41
+ *
42
+ * The `Referrer` header field is special-cased,
43
+ * both `Referrer` and `Referer` are interchangeable.
44
+ *
45
+ * Examples:
46
+ *
47
+ * req.get('Content-Type');
48
+ * // => "text/plain"
49
+ *
50
+ * req.get('content-type');
51
+ * // => "text/plain"
52
+ *
53
+ * req.get('Something');
54
+ * // => undefined
55
+ *
56
+ * Aliased as `req.header()`.
57
+ *
58
+ * @param {String} name
59
+ * @return {String}
60
+ * @public
61
+ */
62
+
63
+ req.get =
64
+ req.header = function header(name) {
65
+ if (!name) {
66
+ throw new TypeError('name argument is required to req.get');
67
+ }
68
+
69
+ if (typeof name !== 'string') {
70
+ throw new TypeError('name must be a string to req.get');
71
+ }
72
+
73
+ var lc = name.toLowerCase();
74
+
75
+ switch (lc) {
76
+ case 'referer':
77
+ case 'referrer':
78
+ return this.headers.referrer
79
+ || this.headers.referer;
80
+ default:
81
+ return this.headers[lc];
82
+ }
83
+ };
84
+
85
+ /**
86
+ * Check if the given `type(s)` is acceptable, returning
87
+ * the best match when true, otherwise `false`, in which
88
+ * case you should respond with 406 "Not Acceptable".
89
+ *
90
+ * The `type` value may be a single MIME type string
91
+ * such as "application/json", an extension name
92
+ * such as "json", an argument list such as `"json", "html", "text/plain"`,
93
+ * or an array `["json", "html", "text/plain"]`. When a list
94
+ * or array is given, the _best_ match, if any is returned.
95
+ *
96
+ * Examples:
97
+ *
98
+ * // Accept: text/html
99
+ * req.accepts('html');
100
+ * // => "html"
101
+ *
102
+ * // Accept: text/*, application/json
103
+ * req.accepts('html');
104
+ * // => "html"
105
+ * req.accepts('text/html');
106
+ * // => "text/html"
107
+ * req.accepts('json', 'text');
108
+ * // => "json"
109
+ * req.accepts('application/json');
110
+ * // => "application/json"
111
+ *
112
+ * // Accept: text/*, application/json
113
+ * req.accepts('image/png');
114
+ * req.accepts('png');
115
+ * // => false
116
+ *
117
+ * // Accept: text/*;q=.5, application/json
118
+ * req.accepts(['html', 'json']);
119
+ * req.accepts('html', 'json');
120
+ * // => "json"
121
+ *
122
+ * @param {String|Array} type(s)
123
+ * @return {String|Array|Boolean}
124
+ * @public
125
+ */
126
+
127
+ req.accepts = function(){
128
+ var accept = accepts(this);
129
+ return accept.types.apply(accept, arguments);
130
+ };
131
+
132
+ /**
133
+ * Check if the given `encoding`s are accepted.
134
+ *
135
+ * @param {String} ...encoding
136
+ * @return {String|Array}
137
+ * @public
138
+ */
139
+
140
+ req.acceptsEncodings = function(){
141
+ var accept = accepts(this);
142
+ return accept.encodings.apply(accept, arguments);
143
+ };
144
+
145
+ /**
146
+ * Checks if the specified `charset`s are acceptable based on the request's `Accept-Charset` header.
147
+ * Returns the best matching charset or an array of acceptable charsets.
148
+ *
149
+ * The `charset` argument(s) can be:
150
+ * - A single charset string (e.g., "utf-8")
151
+ * - Multiple charset strings as arguments (e.g., `"utf-8", "iso-8859-1"`)
152
+ * - A comma-delimited list of charsets (e.g., `"utf-8, iso-8859-1"`)
153
+ *
154
+ * Examples:
155
+ *
156
+ * // Accept-Charset: utf-8, iso-8859-1
157
+ * req.acceptsCharsets('utf-8');
158
+ * // => "utf-8"
159
+ *
160
+ * req.acceptsCharsets('utf-8', 'iso-8859-1');
161
+ * // => "utf-8"
162
+ *
163
+ * req.acceptsCharsets('utf-8, utf-16');
164
+ * // => "utf-8"
165
+ *
166
+ * @param {...String} charsets - The charset(s) to check against the `Accept-Charset` header.
167
+ * @return {String|Array} - The best matching charset, or an array of acceptable charsets.
168
+ * @public
169
+ */
170
+
171
+ req.acceptsCharsets = function(...charsets) {
172
+ const accept = accepts(this);
173
+ return accept.charsets(...charsets);
174
+ };
175
+
176
+ /**
177
+ * Check if the given `lang`s are acceptable,
178
+ * otherwise you should respond with 406 "Not Acceptable".
179
+ *
180
+ * @param {String} ...lang
181
+ * @return {String|Array}
182
+ * @public
183
+ */
184
+
185
+ req.acceptsLanguages = function(...languages) {
186
+ return accepts(this).languages(...languages);
187
+ };
188
+
189
+ /**
190
+ * Parse Range header field, capping to the given `size`.
191
+ *
192
+ * Unspecified ranges such as "0-" require knowledge of your resource length. In
193
+ * the case of a byte range this is of course the total number of bytes. If the
194
+ * Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
195
+ * and `-2` when syntactically invalid.
196
+ *
197
+ * When ranges are returned, the array has a "type" property which is the type of
198
+ * range that is required (most commonly, "bytes"). Each array element is an object
199
+ * with a "start" and "end" property for the portion of the range.
200
+ *
201
+ * The "combine" option can be set to `true` and overlapping & adjacent ranges
202
+ * will be combined into a single range.
203
+ *
204
+ * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
205
+ * should respond with 4 users when available, not 3.
206
+ *
207
+ * @param {number} size
208
+ * @param {object} [options]
209
+ * @param {boolean} [options.combine=false]
210
+ * @return {number|array}
211
+ * @public
212
+ */
213
+
214
+ req.range = function range(size, options) {
215
+ var range = this.get('Range');
216
+ if (!range) return;
217
+ return parseRange(size, range, options);
218
+ };
219
+
220
+ /**
221
+ * Parse the query string of `req.url`.
222
+ *
223
+ * This uses the "query parser" setting to parse the raw
224
+ * string into an object.
225
+ *
226
+ * @return {String}
227
+ * @api public
228
+ */
229
+
230
+ defineGetter(req, 'query', function query(){
231
+ var queryparse = this.app.get('query parser fn');
232
+
233
+ if (!queryparse) {
234
+ // parsing is disabled
235
+ return Object.create(null);
236
+ }
237
+
238
+ var querystring = parse(this).query;
239
+
240
+ return queryparse(querystring);
241
+ });
242
+
243
+ /**
244
+ * Check if the incoming request contains the "Content-Type"
245
+ * header field, and it contains the given mime `type`.
246
+ *
247
+ * Examples:
248
+ *
249
+ * // With Content-Type: text/html; charset=utf-8
250
+ * req.is('html');
251
+ * req.is('text/html');
252
+ * req.is('text/*');
253
+ * // => true
254
+ *
255
+ * // When Content-Type is application/json
256
+ * req.is('json');
257
+ * req.is('application/json');
258
+ * req.is('application/*');
259
+ * // => true
260
+ *
261
+ * req.is('html');
262
+ * // => false
263
+ *
264
+ * @param {String|Array} types...
265
+ * @return {String|false|null}
266
+ * @public
267
+ */
268
+
269
+ req.is = function is(types) {
270
+ var arr = types;
271
+
272
+ // support flattened arguments
273
+ if (!Array.isArray(types)) {
274
+ arr = new Array(arguments.length);
275
+ for (var i = 0; i < arr.length; i++) {
276
+ arr[i] = arguments[i];
277
+ }
278
+ }
279
+
280
+ return typeis(this, arr);
281
+ };
282
+
283
+ /**
284
+ * Return the protocol string "http" or "https"
285
+ * when requested with TLS. When the "trust proxy"
286
+ * setting trusts the socket address, the
287
+ * "X-Forwarded-Proto" header field will be trusted
288
+ * and used if present.
289
+ *
290
+ * If you're running behind a reverse proxy that
291
+ * supplies https for you this may be enabled.
292
+ *
293
+ * @return {String}
294
+ * @public
295
+ */
296
+
297
+ defineGetter(req, 'protocol', function protocol(){
298
+ var proto = this.socket.encrypted
299
+ ? 'https'
300
+ : 'http';
301
+ var trust = this.app.get('trust proxy fn');
302
+
303
+ if (!trust(this.socket.remoteAddress, 0)) {
304
+ return proto;
305
+ }
306
+
307
+ // Note: X-Forwarded-Proto is normally only ever a
308
+ // single value, but this is to be safe.
309
+ var header = this.get('X-Forwarded-Proto') || proto
310
+ var index = header.indexOf(',')
311
+
312
+ return index !== -1
313
+ ? header.substring(0, index).trim()
314
+ : header.trim()
315
+ });
316
+
317
+ /**
318
+ * Short-hand for:
319
+ *
320
+ * req.protocol === 'https'
321
+ *
322
+ * @return {Boolean}
323
+ * @public
324
+ */
325
+
326
+ defineGetter(req, 'secure', function secure(){
327
+ return this.protocol === 'https';
328
+ });
329
+
330
+ /**
331
+ * Return the remote address from the trusted proxy.
332
+ *
333
+ * The is the remote address on the socket unless
334
+ * "trust proxy" is set.
335
+ *
336
+ * @return {String}
337
+ * @public
338
+ */
339
+
340
+ defineGetter(req, 'ip', function ip(){
341
+ var trust = this.app.get('trust proxy fn');
342
+ return proxyaddr(this, trust);
343
+ });
344
+
345
+ /**
346
+ * When "trust proxy" is set, trusted proxy addresses + client.
347
+ *
348
+ * For example if the value were "client, proxy1, proxy2"
349
+ * you would receive the array `["client", "proxy1", "proxy2"]`
350
+ * where "proxy2" is the furthest down-stream and "proxy1" and
351
+ * "proxy2" were trusted.
352
+ *
353
+ * @return {Array}
354
+ * @public
355
+ */
356
+
357
+ defineGetter(req, 'ips', function ips() {
358
+ var trust = this.app.get('trust proxy fn');
359
+ var addrs = proxyaddr.all(this, trust);
360
+
361
+ // reverse the order (to farthest -> closest)
362
+ // and remove socket address
363
+ addrs.reverse().pop()
364
+
365
+ return addrs
366
+ });
367
+
368
+ /**
369
+ * Return subdomains as an array.
370
+ *
371
+ * Subdomains are the dot-separated parts of the host before the main domain of
372
+ * the app. By default, the domain of the app is assumed to be the last two
373
+ * parts of the host. This can be changed by setting "subdomain offset".
374
+ *
375
+ * For example, if the domain is "tobi.ferrets.example.com":
376
+ * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
377
+ * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
378
+ *
379
+ * @return {Array}
380
+ * @public
381
+ */
382
+
383
+ defineGetter(req, 'subdomains', function subdomains() {
384
+ var hostname = this.hostname;
385
+
386
+ if (!hostname) return [];
387
+
388
+ var offset = this.app.get('subdomain offset');
389
+ var subdomains = !isIP(hostname)
390
+ ? hostname.split('.').reverse()
391
+ : [hostname];
392
+
393
+ return subdomains.slice(offset);
394
+ });
395
+
396
+ /**
397
+ * Short-hand for `url.parse(req.url).pathname`.
398
+ *
399
+ * @return {String}
400
+ * @public
401
+ */
402
+
403
+ defineGetter(req, 'path', function path() {
404
+ return parse(this).pathname;
405
+ });
406
+
407
+ /**
408
+ * Parse the "Host" header field to a host.
409
+ *
410
+ * When the "trust proxy" setting trusts the socket
411
+ * address, the "X-Forwarded-Host" header field will
412
+ * be trusted.
413
+ *
414
+ * @return {String}
415
+ * @public
416
+ */
417
+
418
+ defineGetter(req, 'host', function host(){
419
+ var trust = this.app.get('trust proxy fn');
420
+ var val = this.get('X-Forwarded-Host');
421
+
422
+ if (!val || !trust(this.socket.remoteAddress, 0)) {
423
+ val = this.get('Host');
424
+ } else if (val.indexOf(',') !== -1) {
425
+ // Note: X-Forwarded-Host is normally only ever a
426
+ // single value, but this is to be safe.
427
+ val = val.substring(0, val.indexOf(',')).trimRight()
428
+ }
429
+
430
+ return val || undefined;
431
+ });
432
+
433
+ /**
434
+ * Parse the "Host" header field to a hostname.
435
+ *
436
+ * When the "trust proxy" setting trusts the socket
437
+ * address, the "X-Forwarded-Host" header field will
438
+ * be trusted.
439
+ *
440
+ * @return {String}
441
+ * @api public
442
+ */
443
+
444
+ defineGetter(req, 'hostname', function hostname(){
445
+ var host = this.host;
446
+
447
+ if (!host) return;
448
+
449
+ // IPv6 literal support
450
+ var offset = host[0] === '['
451
+ ? host.indexOf(']') + 1
452
+ : 0;
453
+ var index = host.indexOf(':', offset);
454
+
455
+ return index !== -1
456
+ ? host.substring(0, index)
457
+ : host;
458
+ });
459
+
460
+ /**
461
+ * Check if the request is fresh, aka
462
+ * Last-Modified or the ETag
463
+ * still match.
464
+ *
465
+ * @return {Boolean}
466
+ * @public
467
+ */
468
+
469
+ defineGetter(req, 'fresh', function(){
470
+ var method = this.method;
471
+ var res = this.res
472
+ var status = res.statusCode
473
+
474
+ // GET or HEAD for weak freshness validation only
475
+ if ('GET' !== method && 'HEAD' !== method) return false;
476
+
477
+ // 2xx or 304 as per rfc2616 14.26
478
+ if ((status >= 200 && status < 300) || 304 === status) {
479
+ return fresh(this.headers, {
480
+ 'etag': res.get('ETag'),
481
+ 'last-modified': res.get('Last-Modified')
482
+ })
483
+ }
484
+
485
+ return false;
486
+ });
487
+
488
+ /**
489
+ * Check if the request is stale, aka
490
+ * "Last-Modified" and / or the "ETag" for the
491
+ * resource has changed.
492
+ *
493
+ * @return {Boolean}
494
+ * @public
495
+ */
496
+
497
+ defineGetter(req, 'stale', function stale(){
498
+ return !this.fresh;
499
+ });
500
+
501
+ /**
502
+ * Check if the request was an _XMLHttpRequest_.
503
+ *
504
+ * @return {Boolean}
505
+ * @public
506
+ */
507
+
508
+ defineGetter(req, 'xhr', function xhr(){
509
+ var val = this.get('X-Requested-With') || '';
510
+ return val.toLowerCase() === 'xmlhttprequest';
511
+ });
512
+
513
+ /**
514
+ * Helper function for creating a getter on an object.
515
+ *
516
+ * @param {Object} obj
517
+ * @param {String} name
518
+ * @param {Function} getter
519
+ * @private
520
+ */
521
+ function defineGetter(obj, name, getter) {
522
+ Object.defineProperty(obj, name, {
523
+ configurable: true,
524
+ enumerable: true,
525
+ get: getter
526
+ });
527
+ }