Use let or const to avoid scope issues and hoisting
var finalhandler = require('finalhandler');
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}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.