lib/application.js JAVASCRIPT 632 lines View on github.com → Search inside
1/*!2 * express3 * Copyright(c) 2009-2013 TJ Holowaychuk4 * Copyright(c) 2013 Roman Shtylman5 * Copyright(c) 2014-2015 Douglas Christopher Wilson6 * MIT Licensed7 */89'use strict';1011/**12 * Module dependencies.13 * @private14 */1516var finalhandler = require('finalhandler');17var debug = require('debug')('express:application');18var View = require('./view');19var http = require('node:http');20var methods = require('./utils').methods;21var compileETag = require('./utils').compileETag;22var compileQueryParser = require('./utils').compileQueryParser;23var compileTrust = require('./utils').compileTrust;24var resolve = require('node:path').resolve;25var once = require('once')26var Router = require('router');2728/**29 * Module variables.30 * @private31 */3233var slice = Array.prototype.slice;34var flatten = Array.prototype.flat;3536/**37 * Application prototype.38 */3940var app = exports = module.exports = {};4142/**43 * Variable for trust proxy inheritance back-compat44 * @private45 */4647var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';4849/**50 * Initialize the server.51 *52 *   - setup default configuration53 *   - setup default middleware54 *   - setup route reflection methods55 *56 * @private57 */5859app.init = function init() {60  var router = null;6162  this.cache = Object.create(null);63  this.engines = Object.create(null);64  this.settings = Object.create(null);6566  this.defaultConfiguration();6768  // Setup getting to lazily add base router69  Object.defineProperty(this, 'router', {70    configurable: true,71    enumerable: true,72    get: function getrouter() {73      if (router === null) {74        router = new Router({75          caseSensitive: this.enabled('case sensitive routing'),76          strict: this.enabled('strict routing')77        });78      }7980      return router;81    }82  });83};8485/**86 * Initialize application configuration.87 * @private88 */8990app.defaultConfiguration = function defaultConfiguration() {91  var env = process.env.NODE_ENV || 'development';9293  // default settings94  this.enable('x-powered-by');95  this.set('etag', 'weak');96  this.set('env', env);97  this.set('query parser', 'simple')98  this.set('subdomain offset', 2);99  this.set('trust proxy', false);100101  // trust proxy inherit back-compat102  Object.defineProperty(this.settings, trustProxyDefaultSymbol, {103    configurable: true,104    value: true105  });106107  debug('booting in %s mode', env);108109  this.on('mount', function onmount(parent) {110    // inherit trust proxy111    if (this.settings[trustProxyDefaultSymbol] === true112      && typeof parent.settings['trust proxy fn'] === 'function') {113      delete this.settings['trust proxy'];114      delete this.settings['trust proxy fn'];115    }116117    // inherit protos118    Object.setPrototypeOf(this.request, parent.request)119    Object.setPrototypeOf(this.response, parent.response)120    Object.setPrototypeOf(this.engines, parent.engines)121    Object.setPrototypeOf(this.settings, parent.settings)122  });123124  // setup locals125  this.locals = Object.create(null);126127  // top-most app is mounted at /128  this.mountpath = '/';129130  // default locals131  this.locals.settings = this.settings;132133  // default configuration134  this.set('view', View);135  this.set('views', resolve('views'));136  this.set('jsonp callback name', 'callback');137138  if (env === 'production') {139    this.enable('view cache');140  }141};142143/**144 * Dispatch a req, res pair into the application. Starts pipeline processing.145 *146 * If no callback is provided, then default error handlers will respond147 * in the event of an error bubbling through the stack.148 *149 * @private150 */151152app.handle = function handle(req, res, callback) {153  // final handler154  var done = callback || finalhandler(req, res, {155    env: this.get('env'),156    onerror: logerror.bind(this)157  });158159  // set powered by header160  if (this.enabled('x-powered-by')) {161    res.setHeader('X-Powered-By', 'Express');162  }163164  // set circular references165  req.res = res;166  res.req = req;167168  // alter the prototypes169  Object.setPrototypeOf(req, this.request)170  Object.setPrototypeOf(res, this.response)171172  // setup locals173  if (!res.locals) {174    res.locals = Object.create(null);175  }176177  this.router.handle(req, res, done);178};179180/**181 * Proxy `Router#use()` to add middleware to the app router.182 * See Router#use() documentation for details.183 *184 * If the _fn_ parameter is an express app, then it will be185 * mounted at the _route_ specified.186 *187 * @public188 */189190app.use = function use(fn) {191  var offset = 0;192  var path = '/';193194  // default path to '/'195  // disambiguate app.use([fn])196  if (typeof fn !== 'function') {197    var arg = fn;198199    while (Array.isArray(arg) && arg.length !== 0) {200      arg = arg[0];201    }202203    // first arg is the path204    if (typeof arg !== 'function') {205      offset = 1;206      path = fn;207    }208  }209210  var fns = flatten.call(slice.call(arguments, offset), Infinity);211212  if (fns.length === 0) {213    throw new TypeError('app.use() requires a middleware function')214  }215216  // get router217  var router = this.router;218219  fns.forEach(function (fn) {220    // non-express app221    if (!fn || !fn.handle || !fn.set) {222      return router.use(path, fn);223    }224225    debug('.use app under %s', path);226    fn.mountpath = path;227    fn.parent = this;228229    // restore .app property on req and res230    router.use(path, function mounted_app(req, res, next) {231      var orig = req.app;232      fn.handle(req, res, function (err) {233        Object.setPrototypeOf(req, orig.request)234        Object.setPrototypeOf(res, orig.response)235        next(err);236      });237    });238239    // mounted an app240    fn.emit('mount', this);241  }, this);242243  return this;244};245246/**247 * Proxy to the app `Router#route()`248 * Returns a new `Route` instance for the _path_.249 *250 * Routes are isolated middleware stacks for specific paths.251 * See the Route api docs for details.252 *253 * @public254 */255256app.route = function route(path) {257  return this.router.route(path);258};259260/**261 * Register the given template engine callback `fn`262 * as `ext`.263 *264 * By default will `require()` the engine based on the265 * file extension. For example if you try to render266 * a "foo.ejs" file Express will invoke the following internally:267 *268 *     app.engine('ejs', require('ejs').__express);269 *270 * For engines that do not provide `.__express` out of the box,271 * or if you wish to "map" a different extension to the template engine272 * you may use this method. For example mapping the EJS template engine to273 * ".html" files:274 *275 *     app.engine('html', require('ejs').renderFile);276 *277 * In this case EJS provides a `.renderFile()` method with278 * the same signature that Express expects: `(path, options, callback)`,279 * though note that it aliases this method as `ejs.__express` internally280 * so if you're using ".ejs" extensions you don't need to do anything.281 *282 * Some template engines do not follow this convention, the283 * [Consolidate.js](https://github.com/tj/consolidate.js)284 * library was created to map all of node's popular template285 * engines to follow this convention, thus allowing them to286 * work seamlessly within Express.287 *288 * @param {String} ext289 * @param {Function} fn290 * @return {app} for chaining291 * @public292 */293294app.engine = function engine(ext, fn) {295  if (typeof fn !== 'function') {296    throw new Error('callback function required');297  }298299  // get file extension300  var extension = ext[0] !== '.'301    ? '.' + ext302    : ext;303304  // store engine305  this.engines[extension] = fn;306307  return this;308};309310/**311 * Proxy to `Router#param()` with one added api feature. The _name_ parameter312 * can be an array of names.313 *314 * See the Router#param() docs for more details.315 *316 * @param {String|Array} name317 * @param {Function} fn318 * @return {app} for chaining319 * @public320 */321322app.param = function param(name, fn) {323  if (Array.isArray(name)) {324    for (var i = 0; i < name.length; i++) {325      this.param(name[i], fn);326    }327328    return this;329  }330331  this.router.param(name, fn);332333  return this;334};335336/**337 * Assign `setting` to `val`, or return `setting`'s value.338 *339 *    app.set('foo', 'bar');340 *    app.set('foo');341 *    // => "bar"342 *343 * Mounted servers inherit their parent server's settings.344 *345 * @param {String} setting346 * @param {*} [val]347 * @return {Server} for chaining348 * @public349 */350351app.set = function set(setting, val) {352  if (arguments.length === 1) {353    // app.get(setting)354    return this.settings[setting];355  }356357  debug('set "%s" to %o', setting, val);358359  // set value360  this.settings[setting] = val;361362  // trigger matched settings363  switch (setting) {364    case 'etag':365      this.set('etag fn', compileETag(val));366      break;367    case 'query parser':368      this.set('query parser fn', compileQueryParser(val));369      break;370    case 'trust proxy':371      this.set('trust proxy fn', compileTrust(val));372373      // trust proxy inherit back-compat374      Object.defineProperty(this.settings, trustProxyDefaultSymbol, {375        configurable: true,376        value: false377      });378379      break;380  }381382  return this;383};384385/**386 * Return the app's absolute pathname387 * based on the parent(s) that have388 * mounted it.389 *390 * For example if the application was391 * mounted as "/admin", which itself392 * was mounted as "/blog" then the393 * return value would be "/blog/admin".394 *395 * @return {String}396 * @private397 */398399app.path = function path() {400  return this.parent401    ? this.parent.path() + this.mountpath402    : '';403};404405/**406 * Check if `setting` is enabled (truthy).407 *408 *    app.enabled('foo')409 *    // => false410 *411 *    app.enable('foo')412 *    app.enabled('foo')413 *    // => true414 *415 * @param {String} setting416 * @return {Boolean}417 * @public418 */419420app.enabled = function enabled(setting) {421  return Boolean(this.set(setting));422};423424/**425 * Check if `setting` is disabled.426 *427 *    app.disabled('foo')428 *    // => true429 *430 *    app.enable('foo')431 *    app.disabled('foo')432 *    // => false433 *434 * @param {String} setting435 * @return {Boolean}436 * @public437 */438439app.disabled = function disabled(setting) {440  return !this.set(setting);441};442443/**444 * Enable `setting`.445 *446 * @param {String} setting447 * @return {app} for chaining448 * @public449 */450451app.enable = function enable(setting) {452  return this.set(setting, true);453};454455/**456 * Disable `setting`.457 *458 * @param {String} setting459 * @return {app} for chaining460 * @public461 */462463app.disable = function disable(setting) {464  return this.set(setting, false);465};466467/**468 * Delegate `.VERB(...)` calls to `router.VERB(...)`.469 */470471methods.forEach(function (method) {472  app[method] = function (path) {473    if (method === 'get' && arguments.length === 1) {474      // app.get(setting)475      return this.set(path);476    }477478    var route = this.route(path);479    route[method].apply(route, slice.call(arguments, 1));480    return this;481  };482});483484/**485 * Special-cased "all" method, applying the given route `path`,486 * middleware, and callback to _every_ HTTP method.487 *488 * @param {String} path489 * @param {Function} ...490 * @return {app} for chaining491 * @public492 */493494app.all = function all(path) {495  var route = this.route(path);496  var args = slice.call(arguments, 1);497498  for (var i = 0; i < methods.length; i++) {499    route[methods[i]].apply(route, args);500  }501502  return this;503};504505/**506 * Render the given view `name` name with `options`507 * and a callback accepting an error and the508 * rendered template string.509 *510 * Example:511 *512 *    app.render('email', { name: 'Tobi' }, function(err, html){513 *      // ...514 *    })515 *516 * @param {String} name517 * @param {Object|Function} options or fn518 * @param {Function} callback519 * @public520 */521522app.render = function render(name, options, callback) {523  var cache = this.cache;524  var done = callback;525  var engines = this.engines;526  var opts = options || {};527  var view;528529  // support callback function as second arg530  if (typeof options === 'function') {531    done = options;532    opts = {};533  }534535  // merge options536  var renderOptions = { ...this.locals, ...opts._locals, ...opts };537538  // set .cache unless explicitly provided539  if (renderOptions.cache == null) {540    renderOptions.cache = this.enabled('view cache');541  }542543  // primed cache544  if (renderOptions.cache) {545    view = cache[name];546  }547548  // view549  if (!view) {550    var View = this.get('view');551552    view = new View(name, {553      defaultEngine: this.get('view engine'),554      root: this.get('views'),555      engines: engines556    });557558    if (!view.path) {559      var dirs = Array.isArray(view.root) && view.root.length > 1560        ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"'561        : 'directory "' + view.root + '"'562      var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);563      err.view = view;564      return done(err);565    }566567    // prime the cache568    if (renderOptions.cache) {569      cache[name] = view;570    }571  }572573  // render574  tryRender(view, renderOptions, done);575};576577/**578 * Listen for connections.579 *580 * A node `http.Server` is returned, with this581 * application (which is a `Function`) as its582 * callback. If you wish to create both an HTTP583 * and HTTPS server you may do so with the "http"584 * and "https" modules as shown here:585 *586 *    var http = require('node:http')587 *      , https = require('node:https')588 *      , express = require('express')589 *      , app = express();590 *591 *    http.createServer(app).listen(80);592 *    https.createServer({ ... }, app).listen(443);593 *594 * @return {http.Server}595 * @public596 */597598app.listen = function listen() {599  var server = http.createServer(this)600  var args = slice.call(arguments)601  if (typeof args[args.length - 1] === 'function') {602    var done = args[args.length - 1] = once(args[args.length - 1])603    server.once('error', done)604  }605  return server.listen.apply(server, args)606}607608/**609 * Log error using console.error.610 *611 * @param {Error} err612 * @private613 */614615function logerror(err) {616  /* istanbul ignore next */617  if (this.get('env') !== 'test') console.error(err.stack || err.toString());618}619620/**621 * Try rendering a view.622 * @private623 */624625function tryRender(view, options, callback) {626  try {627    view.render(options, callback);628  } catch (err) {629    callback(err);630  }631}

Code quality findings 68

Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var finalhandler = require('finalhandler');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var debug = require('debug')('express:application');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var View = require('./view');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var http = require('node:http');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var methods = require('./utils').methods;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var compileETag = require('./utils').compileETag;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var compileQueryParser = require('./utils').compileQueryParser;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var compileTrust = require('./utils').compileTrust;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var resolve = require('node:path').resolve;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var once = require('once')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var Router = require('router');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var slice = Array.prototype.slice;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var flatten = Array.prototype.flat;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var app = exports = module.exports = {};
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = null;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (router === null) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var env = process.env.NODE_ENV || 'development';
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (this.settings[trustProxyDefaultSymbol] === true
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
&& typeof parent.settings['trust proxy fn'] === 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
&& typeof parent.settings['trust proxy fn'] === 'function') {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (env === 'production') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var done = callback || finalhandler(req, res, {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var offset = 0;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var path = '/';
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof fn !== 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof fn !== 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var arg = fn;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
while (Array.isArray(arg) && arg.length !== 0) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof arg !== 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof arg !== 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var fns = flatten.call(slice.call(arguments, offset), Infinity);
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (fns.length === 0) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var router = this.router;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var orig = req.app;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof fn !== 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof fn !== 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var extension = ext[0] !== '.'
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
var extension = ext[0] !== '.'
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
for (var i = 0; i < name.length; i++) {
Use let instead of var in loops to avoid scope issues
info correctness var-in-loop
for (var i = 0; i < name.length; i++) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (arguments.length === 1) {
Ensure all cases are handled or a default case is present
info correctness switch-without-default
switch (setting) {
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (method === 'get' && arguments.length === 1) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var route = this.route(path);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var route = this.route(path);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var args = slice.call(arguments, 1);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
for (var i = 0; i < methods.length; i++) {
Use let instead of var in loops to avoid scope issues
info correctness var-in-loop
for (var i = 0; i < methods.length; i++) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var cache = this.cache;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var done = callback;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var engines = this.engines;
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var opts = options || {};
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var view;
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof options === 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof options === 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var renderOptions = { ...this.locals, ...opts._locals, ...opts };
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (renderOptions.cache == null) {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var View = this.get('view');
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var dirs = Array.isArray(view.root) && view.root.length > 1
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
* var http = require('node:http')
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var server = http.createServer(this)
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var args = slice.call(arguments)
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (typeof args[args.length - 1] === 'function') {
Be cautious with typeof; it has limitations (e.g., typeof null === 'object')
info correctness typeof-pitfall
if (typeof args[args.length - 1] === 'function') {
Use let or const to avoid scope issues and hoisting
info correctness var-declaration
var done = args[args.length - 1] = once(args[args.length - 1])
Use strict equality (===) to prevent type coercion bugs
info correctness loose-equality
if (this.get('env') !== 'test') console.error(err.stack || err.toString());

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.