Understanding Express Middleware

Summary: in this tutorial, you will learn about Express middleware and understand how it works.

Introduction to Express Middleware

In Express, a middleware is a function that has access to the following objects:

  • The Request object (req).
  • The Response object (res).
  • The next middleware function (next).

Technically, an Express application is a series of middleware function calls:

express middleware

The following defines a middleware function:

function fn(req, res, next) {
   // ...
}Code language: JavaScript (javascript)

Typically, you use middleware to perform the following tasks:

  • Change the request and response objects.
  • Terminate the request-response cycle.
  • Add custom logic to the request/response cycle such as validation, authentication, and authorization.
  • And call the next middleware function.

If you don’t end the request/response cycle in the current middleware function, you must call the next() function to pass control to the next middleware function:

function fn(req, res, next) {
   // ... 
   next();
}Code language: JavaScript (javascript)

The request will be left hanging if you don’t call the next() function.

To end the request/response cycle in a function, you need to send a response back to the client by using one of the following methods:

MethodMeaning
res.send()Send a response body and end the request/response cycle
res.json()Send a JSON response and end the request/response cycle
res.redirect()Redirect the client to another URL and ends the request/response cycle.
res.end()End the request/response cycle without sending any data.

Express middleware types

An Express app can have the following types of middleware:

  • Application-level middleware
  • Router-level middleware
  • Built-in middleware
  • Third-party middleware
  • Error-handling middleware

Application-level middleware

There are two ways to bind an application-level middleware to an instance of the Express app object.

First, pass the middleware function to the app.use() function:

import express from 'express';
const app = express();

// define a middleware
const middleware = (req, res, next) {
    console.log("Execute the middleware");
    next();
}

app.use(middleware);

// ...Code language: JavaScript (javascript)

Second, pass the middleware function to the app.METHOD() function such as app.get(), app.post(), and so on:

import express from 'express';
const app = express();

// define a middleware
const middleware = (req, res, next) {
    console.log("Execute the middleware");
    next();
}

app.get('/', middleware, (req, res) => {
    // route handler
});

// ...Code language: JavaScript (javascript)

Notice that route handlers are also middleware functions:

(req, res) => {
    // ...
}Code language: JavaScript (javascript)

However, a route handler often ends the request/response cycle with a call to res.send() or res.json() method. Therefore, you don’t need to pass the next function and call it inside the router handler.

The following example defines an application middleware that logs the request method and URL in the console window:

import express from 'express';

const PORT = process.env.PORT || 3000;
const app = express();

// define a middleware
const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};

// register the middleware
app.use(log);

// router handlers
app.get('/', (req, res) => {
  res.send('Home');
});

app.get('/about', (req, res) => {
  res.send('About');
});

app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

How it works.

First, define a middleware function called log that displays the URL and method of the request to the console:

const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};Code language: JavaScript (javascript)

Second, register the middleware using the app.use() method:

app.use(log);Code language: JavaScript (javascript)

The log middleware function will execute for every request of all the routes including / and /about.

When you make a GET request to the path / , Express will execute the log middleware function and display the log messages in the console:

Request: GET /Code language: JavaScript (javascript)

Similarly, if you make a GET request to the /about path, the log middleware function will execute and show the following to the console:

Request: GET /aboutCode language: JavaScript (javascript)

Notice that you need to register the middleware before any router handlers. Otherwise, the middleware will not take effect. For example:

import express from 'express';

const PORT = process.env.PORT || 3000;
const app = express();

// define a middleware
const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};

// router handlers
app.get('/', (req, res) => {
  res.send('Home');
});

app.get('/about', (req, res) => {
  res.send('About');
});


// register a middleware
app.use(log); // DO NOT RUN for the / and /about routes


app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

In this example, the middleware registration is after all the router handlers. When you request the / and /about routes, the middleware will not take any effects.

To execute the log middleware function for only the /about method, you can pass it to the corresponding route handler as follows:

// ...

app.get('/about', log, (req, res) => {
  res.send('About');
});

// ...Code language: JavaScript (javascript)

In this case, the log middleware function only executes for the GET method of route /about.

Router-level middleware

The router-level middleware is like an application-level middleware except it is bound to the Router instance instead of the Express app instance.

We’ll discuss the router-level middleware in the Express router tutorial.

Built-in middleware

Express provides some built-in middleware functions:

  • express.json middleware allows you to parse the requests with the JSON body. (available since Express 4.16.0 and later).
  • express.static middleware serves static assets such as HTML files, images, etc.
  • express.urlencoded parses the requests with a URL-encoded body.

Third-party middleware

There are many third-party middleware available. The third-party middleware allows you to enhance the functionality of the Express apps.

Third-party middleware requires installation via package managers such as npm. We’ll introduce you to some of the most commonly used third-party middleware in upcoming tutorials.

Error-handling middleware

Unlike a regular middleware, an error-handling middleware takes four parameters instead of three:

function fn(err, req, res, next) {
   // ...
}Code language: JavaScript (javascript)

The first argument of an error-handling middleware is an error object. We’ll discuss the error-handling middleware in the error-handling tutorial.

Summary

  • A middleware is a function that has access to the request, response, and the next middleware function.
  • Use the app.use() function to register a middleware.
  • Register the middleware before particular router handlers to apply the middleware to these route handlers.
Was this tutorial helpful ?