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

Related Articles

Database Integration in Express.js: A Complete Guide to Popular Node.js Database Drivers

Express.js does not include built‑in database support, but its flexibility allows you to connect it to virtually any database system simply by installing the appropriate Node.js driver. This article provides a complete overview of how to integrate Express with many popular SQL and NoSQL databases, including installation commands and example usage.

Continue

Advanced Express.js: Overriding the API, Template Engines, Debugging, and Working Behind Proxies

Advanced Express.js: Overriding the API, Template Engines, Debugging, and Working Behind Proxies

Continue

Using Middleware in Express.js: A Complete and Practical Guide

Using Middleware in Express.js: A Complete and Practical Guide

Continue

Writing Middleware in Express.js: A Complete Guide for Developers

Middleware is one of the core architectural concepts in Express.js. . Middleware functions have access to the request object (req), the response object (res), and the next() function, which controls the flow of the request–response cycle. Middleware can modify requests, send responses, validate data, log activity, handle errors, or pass control to the next function in the stack. This article explains everything you need to know about writing middleware—from simple examples to async validation, error handling, and configurable middleware.

Continue

Routing in Express.js: A Complete Guide to Application Endpoints

Routing in Express.js defines how an application responds to incoming HTTP requests at specific paths (URIs) and methods. This flexible system allows developers to create simple routes, complex patterns, dynamic parameters, multiple handlers, and modular route structures using Router. This article explains all essential routing concepts—from basic paths to regex routes, route parameters, middleware-style handlers, app.route(), and express.Router.

Continue