Search code examples
node.jsexpressrequesthandler

node express request handler in source code


I'm reading example express source code for my education.

Initializing a simple express application looks like this:

const express = require('express')
const app = express()

app.listen(3000, () => {
  console.log(`http://localhost:3000`)
})

I want to understand what app.listen does in above code.

The source code of app.listen is defined in express/lib/application.js, as following:

var app = exports = module.exports = {};

// ...

app.listen = function listen() {
  var server = http.createServer(this); // <-- why `this` ??
  return server.listen.apply(server, arguments);
};

Typically, http.createServer() accepts a function as request handler. In this case, this was passed in. But this should refer to app, it's not a function, right?

Later I found out app.handle was used as the request handler.

What is happening under the hood?

Thanks for your time!


Solution

  • this is an enhanced instance of the app prototype & it's being used as an options object for http.createServer. To trace this sort of answer, we need to fully understand Node's CommonJS module implementation, the JavaScript prototypical inheritance system & JavaScript function scope.

    The answer lays behind these lines: https://github.com/expressjs/express/blob/4.16.3/lib/application.js#L38 https://github.com/expressjs/express/blob/4.16.3/lib/express.js#L43

    app is a pointer to module.exports, which represents how that module gets interfaced with from other Node modules. That module is only ever used internally by Express in lib/express, where it gets mixed in with another JavaScript prototype before being instantiated. Once an instance, each of the app functions in lib/application share a this that can be used to reference every property value & function on its prototype.

    So...

    Because http.createServer accepts an options object as its 1st argument, ServerResponse & IncomingMessage will be used from app/this if available.

    P.S. do not write code the way the Express team did it. You should never need to look through several modules to find the answer to a simple question like this. There are much simpler & team-friendly approaches to modularizing prototype mixins & default initializer options!