How to Create Middleware in Express.js

Updated: December 28, 2023 By: Guest Contributor Post a comment

Middleware functions are an essential part of any Express.js application. They can perform tasks ranging from logging, parsing, authentication, and more. It’s crucial to understand middleware if you are to develop scalable and maintainable web applications using Express.js.

What is middleware?

In Express.js, middleware functions have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. These functions can:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware function in the stack.

If the current middleware does not end the cycle, it must call next() to pass control to the next middleware, otherwise the request will be left hanging.

How to create middleware

Creating middleware is straightforward. A middleware function typically has this structure:

function myMiddleware(req, res, next) {
  // Middleware code
  next();
}

To apply it to your app:

const express = require('express');
const app = express();

app.use(myMiddleware);

Example: Logging Middleware

function logger(req, res, next) {
  console.log(
    `${new Date().toISOString()} - ${req.method} request to ${req.url}`
  );
  next();
}

app.use(logger);

How to use middleware

Middleware can be applied globally to all routes using app.use(), or it can be applied to specific routes:

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

It’s also possible to stack multiple middleware functions:

app.use(middleware1, middleware2, middleware3);

Express middleware & TypeScript example

Below is a complete example of an Express application written in TypeScript. This example includes a custom middleware and demonstrates basic routing. To run this, you’ll need Node.js installed and will have to set up a TypeScript environment.

First, ensure you have TypeScript and the necessary type definitions for Node and Express. You can install them via npm:

npm install typescript @types/node @types/express

Now, here’s the TypeScript code for a simple Express server (server.ts):

import express, { Request, Response, NextFunction } from 'express';

// Define a port
const PORT = 3000;

// Create an Express application
const app = express();

// Custom middleware that logs the request method and URL
const loggerMiddleware = (req: Request, res: Response, next: NextFunction): void => {
    console.log(`${req.method} ${req.path}`);
    next();
};

// Use the logger middleware in the app
app.use(loggerMiddleware);

// A GET route
app.get('/', (req: Request, res: Response) => {
    res.send('Hello World!');
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is running at http://localhost:${PORT}`);
});

To run this code, you’ll also need a tsconfig.json file for TypeScript configuration. Here’s a basic example:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "./dist"
  }
}

Compile the TypeScript code to JavaScript using the TypeScript compiler:

tsc

This will compile your TypeScript code into JavaScript in the ./dist directory. You can then run your compiled server with Node.js:

node ./dist/server.js

This will start an Express server on port 3000, and you can visit http://localhost:3000 in your browser to see the output. The logger middleware will log all incoming requests to the console.

Conclusion

In summary, understanding how to create and use middleware is key to building applications with Express.js. With middleware, you can control the request-response cycle, manage cross-cutting concerns, and write cleaner, more modular code. Don’t hesitate to break up complex functionality into smaller middleware functions, making them easy to read and maintain.