# Behavior traces — expressjs/express

> Canonical page: https://codevetter.com/unpack/express/behavior-traces

# Behavior traces — expressjs/express

Scanned commit 9a34acf03cb818ff3f8bc40e44176e277a25cbb9 (2026-09-15). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Four flows carry essentially all of Express's behaviour: application construction, request dispatch, response emission, and view rendering. Each is short and traceable by name — the framework is only three or four stack frames deep before control reaches an external package. The traces below name functions in call order as they appear in `lib/`.
- STARTUP: `require('express')` → `index.js` → `lib/express.js` → user calls `createApplication()` → `mixin(app, EventEmitter.prototype)` → `mixin(app, proto)` → `Object.create(req/res)` → `app.init()` → `app.defaultConfiguration()` → settings seeded and the `'mount'` listener attached → `Object.defineProperty(this, 'router', getter)` installs the lazy router. — [index.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/index.js) [lib/express.js#L36-L56](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L36-L56) [lib/application.js#L59-L145](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L59-L145)
- STARTUP (server): `app.listen(...)` → `http.createServer(this)` → if the last arg is a function it is wrapped with `once()` and registered on the server's `'error'` event → `server.listen.apply(server, args)`; the returned value is the `http.Server`, not the app. — [lib/application.js#L598-L607](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L598-L607) [test/app.listen.js#L13-L26](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/app.listen.js#L13-L26)
- ROUTE REGISTRATION: `app.get('/x', fn)` → generated method sees `arguments.length > 1` → `this.route(path)` → `this.router.route(path)` (first access instantiates `new Router`) → `route.get(fn)`. — [lib/application.js#L471-L483](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L471-L483) [lib/application.js#L259-L261](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L259-L261) [lib/application.js#L70-L82](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L70-L82)
- DISPATCH: socket → `app(req, res)` closure → `app.handle` → `finalhandler(...)` built → `res.setHeader('X-Powered-By')` → `req.res`/`res.req` cross-links → both prototypes swapped → `res.locals` ensured → `this.router.handle(req, res, done)` hands off to the external router package. — [lib/express.js#L37-L39](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/express.js#L37-L39) [lib/application.js#L152-L182](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L152-L182)
- PRIMARY ACTION (`res.send('hi')`): typeof-string branch sets charset via `setCharset` or `this.type('html')` → `app.get('etag fn')` → length computed and `Content-Length` set unless `Transfer-Encoding` present → `etagFn(chunk, encoding)` → `this.set('ETag')` → `if (req.fresh) this.status(304)` → header stripping for 204/304/205 → `this.end(chunk, encoding)` (or bare `end()` for HEAD). — [lib/response.js#L126-L226](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L126-L226) [lib/utils.js#L225-L241](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/utils.js#L225-L241)
- JSON PATH: `res.json(obj)` → reads `json escape`/`json replacer`/`json spaces` → `stringify()` → sets `Content-Type: application/json` only if unset → delegates to `res.send(body)`, which then re-enters the string branch and applies the charset. — [lib/response.js#L236-L260](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L236-L260) [lib/response.js#L126-L150](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L126-L150)
- JSONP PATH: `res.jsonp` → `stringify()` → reads the callback from `req.query[app.get('jsonp callback name')]` → takes `callback[0]` if an array → strips everything outside `[^\[\]\w$.]` → sets `X-Content-Type-Options: nosniff` and `text/javascript` → escapes U+2028/U+2029 → wraps in the `/**/ typeof cb === 'function' && cb(...)` Rosetta-Flash mitigation → `res.send`. — [lib/response.js#L264-L318](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L264-L318) [test/res.jsonp.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/res.jsonp.js)
- RENDER PATH: `res.render(view, opts)` → `opts._locals = res.locals` → default callback `(err, str) => err ? req.next(err) : self.send(str)` → `app.render(name, opts, done)` → locals merged → cache consulted → `new View(name, { defaultEngine, root, engines })` → `view.lookup()` → `View#resolve` → `tryStat` → `tryRender(view, opts, done)` → `View#render` → engine → `process.nextTick` → `res.send(html)`. — [lib/response.js#L896-L920](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L896-L920) [lib/application.js#L522-L583](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L522-L583) [lib/view.js#L104-L192](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/view.js#L104-L192)
- ENGINE RESOLUTION: inside the `View` constructor, if `opts.engines[this.ext]` is missing, Express computes `mod = this.ext.slice(1)` and performs a dynamic `require(mod).__express`, throwing `Module "x" does not provide a view engine.` when that export is not a function. — [lib/view.js#L74-L88](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/view.js#L74-L88) [test/app.render.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/app.render.js)
- VIEW LOOKUP fallback: `View#resolve` first tries `<dir>/<file>` and, failing that, `<dir>/<basename>/index<ext>` — both via synchronous `fs.statSync` wrapped in `tryStat`. — [lib/view.js#L169-L204](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/view.js#L169-L204)
- FILE TRANSFER: `res.sendFile` → argument validation (throws on missing/non-string path, and on a relative path with no `root`) → `encodeURI(path)` → `opts.etag = app.enabled('etag')` → `send(req, pathname, opts)` → `sendfile(res, file, opts, cb)` → listeners registered → `file.pipe(res)`; the `onfinish` handler uses `setImmediate` to distinguish a completed stream from an aborted one. — [lib/response.js#L375-L430](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L375-L430) [lib/response.js#L923-L1010](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L923-L1010)
- DOWNLOAD: `res.download` → argument shuffling for the (filename|options|callback) overloads → `Content-Disposition` built from `basename(name || path)` → caller headers copied except `content-disposition` → `opts = Object.create(opts)` so user options stay on the prototype → `resolve(path)` when no `root` → `this.sendFile(fullPath, opts, done)`. — [lib/response.js#L437-L486](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L437-L486)
- REDIRECT: `res.redirect([status,] url)` → optional `depd` deprecation calls → `this.location(address)` runs `encodeUrl` and re-reads the header → `res.format({ text, html, default })` picks a body → `res.status(status)` → explicit `Content-Length` via `Buffer.byteLength` → `end()` (body skipped for HEAD). — [lib/response.js#L796-L870](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/response.js#L796-L870)
- SUB-APP MOUNT: `app.use('/admin', subApp)` → duck-type check passes → `subApp.mountpath = '/admin'`, `subApp.parent = this` → `router.use(path, mounted_app)` → `subApp.emit('mount', this)` → the child's `'mount'` listener re-parents its `request`/`response`/`engines`/`settings` prototypes; at request time `mounted_app` restores `orig.request`/`orig.response` before calling `next`. — [lib/application.js#L190-L241](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L190-L241) [lib/application.js#L109-L123](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L109-L123) [test/app.use.js](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/test/app.use.js)
- ERROR EXIT: when no handler responds, control returns to the `done` built in `app.handle`; `finalhandler`'s `onerror` is bound to `logerror`, which `console.error`s unless `app.get('env') === 'test'`. — [lib/application.js#L153-L158](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L153-L158) [lib/application.js#L610-L618](https://github.com/expressjs/express/blob/9a34acf03cb818ff3f8bc40e44176e277a25cbb9/lib/application.js#L610-L618)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
