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:

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

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

The following defines a middleware function:

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

A middleware allows you to perform the following tasks:

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

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.

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 the route handler is also a middleware function:

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

However, a route handler often ends the request/response cycle. Therefore, you don’t need to pass the next middleware 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 a 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 the GET request to the / , Express will execute the log middleware function and show the log in the console:

Request: GET /Code language: JavaScript (javascript)

Similarly, if you make a GET request to the /about route, 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 all router handlers to apply the middleware to all the route handlers.
  • Pass a middleware to a router handler such as app.get() to register the middleware for a particular router.
Was this tutorial helpful ?