Merge "LOG SQL dump files getting installed"
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / express / lib / application.js
1 /**
2  * Module dependencies.
3  */
4
5 var finalhandler = require('finalhandler');
6 var flatten = require('./utils').flatten;
7 var Router = require('./router');
8 var methods = require('methods');
9 var middleware = require('./middleware/init');
10 var query = require('./middleware/query');
11 var debug = require('debug')('express:application');
12 var View = require('./view');
13 var http = require('http');
14 var compileETag = require('./utils').compileETag;
15 var compileQueryParser = require('./utils').compileQueryParser;
16 var compileTrust = require('./utils').compileTrust;
17 var deprecate = require('depd')('express');
18 var merge = require('utils-merge');
19 var resolve = require('path').resolve;
20 var slice = Array.prototype.slice;
21
22 /**
23  * Application prototype.
24  */
25
26 var app = exports = module.exports = {};
27
28 /**
29  * Initialize the server.
30  *
31  *   - setup default configuration
32  *   - setup default middleware
33  *   - setup route reflection methods
34  *
35  * @api private
36  */
37
38 app.init = function(){
39   this.cache = {};
40   this.settings = {};
41   this.engines = {};
42   this.defaultConfiguration();
43 };
44
45 /**
46  * Initialize application configuration.
47  *
48  * @api private
49  */
50
51 app.defaultConfiguration = function(){
52   // default settings
53   this.enable('x-powered-by');
54   this.set('etag', 'weak');
55   var env = process.env.NODE_ENV || 'development';
56   this.set('env', env);
57   this.set('query parser', 'extended');
58   this.set('subdomain offset', 2);
59   this.set('trust proxy', false);
60
61   debug('booting in %s mode', env);
62
63   // inherit protos
64   this.on('mount', function(parent){
65     this.request.__proto__ = parent.request;
66     this.response.__proto__ = parent.response;
67     this.engines.__proto__ = parent.engines;
68     this.settings.__proto__ = parent.settings;
69   });
70
71   // setup locals
72   this.locals = Object.create(null);
73
74   // top-most app is mounted at /
75   this.mountpath = '/';
76
77   // default locals
78   this.locals.settings = this.settings;
79
80   // default configuration
81   this.set('view', View);
82   this.set('views', resolve('views'));
83   this.set('jsonp callback name', 'callback');
84
85   if (env === 'production') {
86     this.enable('view cache');
87   }
88
89   Object.defineProperty(this, 'router', {
90     get: function() {
91       throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
92     }
93   });
94 };
95
96 /**
97  * lazily adds the base router if it has not yet been added.
98  *
99  * We cannot add the base router in the defaultConfiguration because
100  * it reads app settings which might be set after that has run.
101  *
102  * @api private
103  */
104 app.lazyrouter = function() {
105   if (!this._router) {
106     this._router = new Router({
107       caseSensitive: this.enabled('case sensitive routing'),
108       strict: this.enabled('strict routing')
109     });
110
111     this._router.use(query(this.get('query parser fn')));
112     this._router.use(middleware.init(this));
113   }
114 };
115
116 /**
117  * Dispatch a req, res pair into the application. Starts pipeline processing.
118  *
119  * If no _done_ callback is provided, then default error handlers will respond
120  * in the event of an error bubbling through the stack.
121  *
122  * @api private
123  */
124
125 app.handle = function(req, res, done) {
126   var router = this._router;
127
128   // final handler
129   done = done || finalhandler(req, res, {
130     env: this.get('env'),
131     onerror: logerror.bind(this)
132   });
133
134   // no routes
135   if (!router) {
136     debug('no routes defined on app');
137     done();
138     return;
139   }
140
141   router.handle(req, res, done);
142 };
143
144 /**
145  * Proxy `Router#use()` to add middleware to the app router.
146  * See Router#use() documentation for details.
147  *
148  * If the _fn_ parameter is an express app, then it will be
149  * mounted at the _route_ specified.
150  *
151  * @api public
152  */
153
154 app.use = function use(fn) {
155   var offset = 0;
156   var path = '/';
157
158   // default path to '/'
159   // disambiguate app.use([fn])
160   if (typeof fn !== 'function') {
161     var arg = fn;
162
163     while (Array.isArray(arg) && arg.length !== 0) {
164       arg = arg[0];
165     }
166
167     // first arg is the path
168     if (typeof arg !== 'function') {
169       offset = 1;
170       path = fn;
171     }
172   }
173
174   var fns = flatten(slice.call(arguments, offset));
175
176   if (fns.length === 0) {
177     throw new TypeError('app.use() requires middleware functions');
178   }
179
180   // setup router
181   this.lazyrouter();
182   var router = this._router;
183
184   fns.forEach(function (fn) {
185     // non-express app
186     if (!fn || !fn.handle || !fn.set) {
187       return router.use(path, fn);
188     }
189
190     debug('.use app under %s', path);
191     fn.mountpath = path;
192     fn.parent = this;
193
194     // restore .app property on req and res
195     router.use(path, function mounted_app(req, res, next) {
196       var orig = req.app;
197       fn.handle(req, res, function (err) {
198         req.__proto__ = orig.request;
199         res.__proto__ = orig.response;
200         next(err);
201       });
202     });
203
204     // mounted an app
205     fn.emit('mount', this);
206   }, this);
207
208   return this;
209 };
210
211 /**
212  * Proxy to the app `Router#route()`
213  * Returns a new `Route` instance for the _path_.
214  *
215  * Routes are isolated middleware stacks for specific paths.
216  * See the Route api docs for details.
217  *
218  * @api public
219  */
220
221 app.route = function(path){
222   this.lazyrouter();
223   return this._router.route(path);
224 };
225
226 /**
227  * Register the given template engine callback `fn`
228  * as `ext`.
229  *
230  * By default will `require()` the engine based on the
231  * file extension. For example if you try to render
232  * a "foo.jade" file Express will invoke the following internally:
233  *
234  *     app.engine('jade', require('jade').__express);
235  *
236  * For engines that do not provide `.__express` out of the box,
237  * or if you wish to "map" a different extension to the template engine
238  * you may use this method. For example mapping the EJS template engine to
239  * ".html" files:
240  *
241  *     app.engine('html', require('ejs').renderFile);
242  *
243  * In this case EJS provides a `.renderFile()` method with
244  * the same signature that Express expects: `(path, options, callback)`,
245  * though note that it aliases this method as `ejs.__express` internally
246  * so if you're using ".ejs" extensions you dont need to do anything.
247  *
248  * Some template engines do not follow this convention, the
249  * [Consolidate.js](https://github.com/tj/consolidate.js)
250  * library was created to map all of node's popular template
251  * engines to follow this convention, thus allowing them to
252  * work seamlessly within Express.
253  *
254  * @param {String} ext
255  * @param {Function} fn
256  * @return {app} for chaining
257  * @api public
258  */
259
260 app.engine = function(ext, fn){
261   if ('function' != typeof fn) throw new Error('callback function required');
262   if ('.' != ext[0]) ext = '.' + ext;
263   this.engines[ext] = fn;
264   return this;
265 };
266
267 /**
268  * Proxy to `Router#param()` with one added api feature. The _name_ parameter
269  * can be an array of names.
270  *
271  * See the Router#param() docs for more details.
272  *
273  * @param {String|Array} name
274  * @param {Function} fn
275  * @return {app} for chaining
276  * @api public
277  */
278
279 app.param = function(name, fn){
280   this.lazyrouter();
281
282   if (Array.isArray(name)) {
283     name.forEach(function(key) {
284       this.param(key, fn);
285     }, this);
286     return this;
287   }
288
289   this._router.param(name, fn);
290   return this;
291 };
292
293 /**
294  * Assign `setting` to `val`, or return `setting`'s value.
295  *
296  *    app.set('foo', 'bar');
297  *    app.get('foo');
298  *    // => "bar"
299  *
300  * Mounted servers inherit their parent server's settings.
301  *
302  * @param {String} setting
303  * @param {*} [val]
304  * @return {Server} for chaining
305  * @api public
306  */
307
308 app.set = function(setting, val){
309   if (arguments.length === 1) {
310     // app.get(setting)
311     return this.settings[setting];
312   }
313
314   // set value
315   this.settings[setting] = val;
316
317   // trigger matched settings
318   switch (setting) {
319     case 'etag':
320       debug('compile etag %s', val);
321       this.set('etag fn', compileETag(val));
322       break;
323     case 'query parser':
324       debug('compile query parser %s', val);
325       this.set('query parser fn', compileQueryParser(val));
326       break;
327     case 'trust proxy':
328       debug('compile trust proxy %s', val);
329       this.set('trust proxy fn', compileTrust(val));
330       break;
331   }
332
333   return this;
334 };
335
336 /**
337  * Return the app's absolute pathname
338  * based on the parent(s) that have
339  * mounted it.
340  *
341  * For example if the application was
342  * mounted as "/admin", which itself
343  * was mounted as "/blog" then the
344  * return value would be "/blog/admin".
345  *
346  * @return {String}
347  * @api private
348  */
349
350 app.path = function(){
351   return this.parent
352     ? this.parent.path() + this.mountpath
353     : '';
354 };
355
356 /**
357  * Check if `setting` is enabled (truthy).
358  *
359  *    app.enabled('foo')
360  *    // => false
361  *
362  *    app.enable('foo')
363  *    app.enabled('foo')
364  *    // => true
365  *
366  * @param {String} setting
367  * @return {Boolean}
368  * @api public
369  */
370
371 app.enabled = function(setting){
372   return !!this.set(setting);
373 };
374
375 /**
376  * Check if `setting` is disabled.
377  *
378  *    app.disabled('foo')
379  *    // => true
380  *
381  *    app.enable('foo')
382  *    app.disabled('foo')
383  *    // => false
384  *
385  * @param {String} setting
386  * @return {Boolean}
387  * @api public
388  */
389
390 app.disabled = function(setting){
391   return !this.set(setting);
392 };
393
394 /**
395  * Enable `setting`.
396  *
397  * @param {String} setting
398  * @return {app} for chaining
399  * @api public
400  */
401
402 app.enable = function(setting){
403   return this.set(setting, true);
404 };
405
406 /**
407  * Disable `setting`.
408  *
409  * @param {String} setting
410  * @return {app} for chaining
411  * @api public
412  */
413
414 app.disable = function(setting){
415   return this.set(setting, false);
416 };
417
418 /**
419  * Delegate `.VERB(...)` calls to `router.VERB(...)`.
420  */
421
422 methods.forEach(function(method){
423   app[method] = function(path){
424     if ('get' == method && 1 == arguments.length) return this.set(path);
425
426     this.lazyrouter();
427
428     var route = this._router.route(path);
429     route[method].apply(route, slice.call(arguments, 1));
430     return this;
431   };
432 });
433
434 /**
435  * Special-cased "all" method, applying the given route `path`,
436  * middleware, and callback to _every_ HTTP method.
437  *
438  * @param {String} path
439  * @param {Function} ...
440  * @return {app} for chaining
441  * @api public
442  */
443
444 app.all = function(path){
445   this.lazyrouter();
446
447   var route = this._router.route(path);
448   var args = slice.call(arguments, 1);
449   methods.forEach(function(method){
450     route[method].apply(route, args);
451   });
452
453   return this;
454 };
455
456 // del -> delete alias
457
458 app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
459
460 /**
461  * Render the given view `name` name with `options`
462  * and a callback accepting an error and the
463  * rendered template string.
464  *
465  * Example:
466  *
467  *    app.render('email', { name: 'Tobi' }, function(err, html){
468  *      // ...
469  *    })
470  *
471  * @param {String} name
472  * @param {String|Function} options or fn
473  * @param {Function} fn
474  * @api public
475  */
476
477 app.render = function(name, options, fn){
478   var opts = {};
479   var cache = this.cache;
480   var engines = this.engines;
481   var view;
482
483   // support callback function as second arg
484   if ('function' == typeof options) {
485     fn = options, options = {};
486   }
487
488   // merge app.locals
489   merge(opts, this.locals);
490
491   // merge options._locals
492   if (options._locals) {
493     merge(opts, options._locals);
494   }
495
496   // merge options
497   merge(opts, options);
498
499   // set .cache unless explicitly provided
500   opts.cache = null == opts.cache
501     ? this.enabled('view cache')
502     : opts.cache;
503
504   // primed cache
505   if (opts.cache) view = cache[name];
506
507   // view
508   if (!view) {
509     view = new (this.get('view'))(name, {
510       defaultEngine: this.get('view engine'),
511       root: this.get('views'),
512       engines: engines
513     });
514
515     if (!view.path) {
516       var dirs = Array.isArray(view.root) && view.root.length > 1
517         ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"'
518         : 'directory "' + view.root + '"'
519       var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);
520       err.view = view;
521       return fn(err);
522     }
523
524     // prime the cache
525     if (opts.cache) cache[name] = view;
526   }
527
528   // render
529   try {
530     view.render(opts, fn);
531   } catch (err) {
532     fn(err);
533   }
534 };
535
536 /**
537  * Listen for connections.
538  *
539  * A node `http.Server` is returned, with this
540  * application (which is a `Function`) as its
541  * callback. If you wish to create both an HTTP
542  * and HTTPS server you may do so with the "http"
543  * and "https" modules as shown here:
544  *
545  *    var http = require('http')
546  *      , https = require('https')
547  *      , express = require('express')
548  *      , app = express();
549  *
550  *    http.createServer(app).listen(80);
551  *    https.createServer({ ... }, app).listen(443);
552  *
553  * @return {http.Server}
554  * @api public
555  */
556
557 app.listen = function(){
558   var server = http.createServer(this);
559   return server.listen.apply(server, arguments);
560 };
561
562 /**
563 * Log error using console.error.
564 *
565 * @param {Error} err
566 * @api private
567 */
568
569 function logerror(err){
570   if (this.get('env') !== 'test') console.error(err.stack || err.toString());
571 }