How to use middleware in express.js

How to use middleware in express.js

Introduction

Express middlewares are functions that sit between the request and response cycle. These functions have access to the request and response objects and can intercept and change these objects. These middlewares are functions that can run codes, make changes to the request-response cycle

Why use express middlewares

  • Security: express middlewares are used to improve the security of an application. This makes sure that only authorized users can access a particular resource on the application
  • Improved functionality: express middlewares improve and extend the functionality of the application by adding extra features needed in the application. example express.json() middleware helps the application parse JSON data.
  • Error handling: custom error handling middleware makes error handling better and more efficient throughout the application. By defining custom error-handling middleware, you can intercept and process errors from any route, logging or formatting them consistently for all routes.
  • Code organization and reusability: functionalities like error handling, authentication, and logging can be separated into individual functions. This separation leads to cleaner, more maintainable code since each middleware has a specific purpose and can be reused across multiple routes.

Types of middlewares and how to use them

Global middleware / application-level middleware

This middleware exists on the application level. This makes it available to all routes. It is bound to the app instance using app.use().

const express = require("express")
const app = express()

app.use(logMethod)

app.get("/", (req, res) => {
    res.send("Hello world");
});

function logMethod(req, res, next) {
    console.log(req.method);
    next()
}

app.listen(3000, () => console.log(`server started on 3000`));

This is a basic express server setup. The logMethod function is the middleware which is used as a global middleware using the app.use(logMethod). The logMethod function has three parameters req which is the request object, res this is the response object and next is a function that calls the next middleware to run.
The logMethod middleware is a very basic middleware that logs the request method to the console. It is important to note that without the next() function the next middleware would not run.

Route-specific middleware

This type of middleware is specific only to the route that uses it, unlike global middleware which is available to all the routes in the application. This type of middleware is commonly used as an authentication guard to protect routes that only authenticated users can access.

const express = require("express")
const app = express()


app.get("/user_details", checkAuth, (req, res) => {
    res.send("This is the user's details page");
});


app.get("/about", (req, res) => {
    res.send("This is an about page")
})


function checkAuth(req, res, next) {
    if (req.query.authenticated === 'true') {
        next()
    } else {
        res.status(401).send("Not authorized");
    }
}

app.listen(3000, () => console.log(`server started on 3000`));

We have two routes, a protected route and a public route. The protected route is guarded with the checkAuth middleware. This middleware checks if the user is authenticated, for the sake of this tutorial we will be using a basic authentication logic, this logic checks if the authenticated query parameter (http://localhost:3000/user_details?authenticated=true) is set to true if not it sends the user out with the 401 HTTP code.

Built-in middleware

These are middlewares that come with the express package. They are built into the express package, so there is no need to write custom functions or install additional packages to use these middlewares They help extend the functionality of the express.js package and make performing common tasks easier. Built-in middlewares are mostly set as global middlewares using the app.use()

const express = require("express")
const app = express()

app.use(express.json())
app.use(express.urlencoded({extended: false}));


app.get("/about", (req, res) => {
    console.log(req.body)
    res.send("This is an about page")
})


app.listen(3000, () => console.log(`server started on 3000`));
  • express.json() is a middleware that parses incoming requests with JSON payloads. Without this middleware, the req.body object will be empty or undefined. This middleware accepts an object as an argument to further configure the behaviour to suit your use case.
  • express.urlencoded() is a middleware that handles incoming requests with urlencoded payload. This populates the req.body object with the parsed data. This middleware also accepts an object as an argument to further configure the behaviour to suit your use case.

Error-handling middleware

This middleware is used to make error handling better. For a middleware to be regarded as an error handling middleware, it must take four arguments (err, req, res, next). The new argument here that makes it different from other types of middleware is the err argument. This argument contains details about the error.

const express = require("express")
const app = express()


app.get("/about", (req, res, next) => {
    const err = new Error("Something went wrong")
    next(err)
})

app.use(errorHandler);

function errorHandler(err, req, res, next) {
    if (err) {
        console.log(err.message)
        res.status(400).send(err);
    }
}


app.listen(3000, () => console.log(`server started on 3000`));

The errorHandler middleware takes four arguments (err, req, res, next), we check if there is any error on the err parameter then log the error message to the console and send the error to the client.

Notice that the GET route has a third argument of next this is because route actions are also middleware and the next() function calls the next middleware which is the errorHandler also the app.use(errorHandler) is called after the GET route this is because middlewares are executed in the order by which they were called. It is also important to make sure that the endpoint runs before the middleware to ensure proper error handling in this case.

Third party middlewares

These are middlewares used to extend express application functionality to suit your use case. To use these middlewares, the package needs to be installed with node package manager (NPM) or yarn. Examples of third-party middleware are.

  • Cors(): This package is used to handle cross-origin resource sharing (CORS). With this package origins that can access resources within the express server can be managed.
  • Multer: This is similar to built-in express.json() and express.urlencoded the difference is this package parses formdata, this makes it possible to upload files in an express server.
  • Body-parser: Body parser transforms incoming data in different formats like JSON, URL-encoded form data, raw text, or other formats into readable format making it accessible via req.body object. This middleware is very similar to built-in express.json() and express.urlencoded. This middleware transforms more content types.

Conclusion

In this tutorial, we looked at express middleware, a very important feature in the Express.js framework. Middlewares add extra functionalities that make managing important features like authentication, parsing data in different and cross-origin resource sharing (CORS) easier. If you're a beginner looking for more information about the Express.js framework, head to the official documentation. HAPPY CODING!