Overriding the Express API and Using Template Engines

Overriding the Express API and Using Template Engines

Express API Overrideexpress.request / express.responseapp.request / app.responseTemplate EnginePug / EJS / HandlebarsPrototype Extension

~2 min read • Updated Dec 26, 2025

1. Overriding the Express API


Express exposes various methods and properties on req and res. These are inherited through prototypes, which makes overriding or extending them possible.

There are two extension points:

  • Global level: express.request and express.response
  • App level: app.request and app.response

Global changes affect all Express apps in the same process. App‑level changes affect only the specific app instance.

2. Overriding Methods


You can override existing methods by assigning a new function.

Example: Overriding res.sendStatus

app.response.sendStatus = function (statusCode, type, message) {
  return this.contentType(type)
    .status(statusCode)
    .send(message)
}

Now the method accepts three arguments:

res.sendStatus(404, 'application/json', '{"error":"resource not found"}')

3. Overriding Properties


Express properties fall into two categories:

  • Assigned properties (e.g., req.baseUrl) — cannot be overridden.
  • Getter properties (e.g., req.ip) — can be overridden.

Example: Overriding req.ip

Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get () { return this.get('Client-IP') }
})

Now the IP address is derived from the Client-IP header.

4. Changing the Prototype


By default, Express uses:

  • http.IncomingRequest.prototype for requests
  • http.ServerResponse.prototype for responses

You can replace these prototypes if needed, but it’s recommended to do so only at the app level.

Example:

Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype)
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype)

5. Using Template Engines in Express


Template engines allow you to use static template files and inject dynamic values at runtime to generate HTML pages.

Express supports many engines:

  • Pug (default)
  • EJS
  • Handlebars
  • Any engine supported by @ladjs/consolidate

6. Configuring a Template Engine


In your app.js, configure:

app.set('views', './views')
app.set('view engine', 'pug')

Install Pug:

npm install pug --save

7. Creating a Template File (Pug)


File: views/index.pug

html
  head
    title= title
  body
    h1= message

8. Rendering the Template


app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' })
})

Visiting the home page renders the Pug template as HTML.

9. Template Engine Cache


The cache stores the compiled template, not the rendered HTML. The template is re-rendered on every request.

Conclusion


Express is highly flexible. By overriding the API, you can customize the behavior of req and res, and with template engines, you can generate dynamic HTML pages. Together, these features make Express a powerful tool for building modern web applications.

Written & researched by Dr. Shahin Siami