How to Use Application-Level Middleware with Express.js and TypeScript

Note: This post is part of Learn How to Use TypeScript With Node.js and Express.js series. Click here to see the first post of the series.

What Are Application-Level Middleware and Why Do We Need Them?

Application-level middleware is a type of middleware that generally runs throughout the whole application. In the case of express.js, this kind of middleware are bound to the application by using app.use(). This means a middleware will be executed for all endpoints set in the application, unless we specify a specific path.

 

// use application-level middleware for all API endpoints
app.use(applicationLevelMiddleware());

// use application-level middleware for all API endpoints with the path of http://localhost:${port}/api/*
app.use('/api/', applicationLevelMiddleware());
 

We can use application-level middleware in express by using app.METHOD() or a request method (GET, POST, PUT, DELETE). The endpoint with a specific request METHOD at a given route will need to go through a middleware first.


// use application-level middleware for http://localhost:${port}/api/ GET API endpoint
app.get('/api/', applicationLevelMiddleware());

Create a Logging Application-Level Middleware

Logging, a simple but yet important feature of any application, is an excellent candidate for application-level middleware. Logging will allow you to know exactly what time and, depending on the application, who triggered an API endpoint.

To create our middleware, we are going to create a middlewares folder inside the src/api folder. Feel free to create in a different location based on your application. However, if you are following the Learn How to Use TypeScript With Node.js and Express.js series, src/api/middlewares will be the location used for the series. Then, create a file called logger.middleware.ts and before we add the middleware logic, we are going to install uuid package.


npm i -s uuid
npm i -D @types/uuid

Let’s also install chalk. Chalk is a nifty package to add color to the logs.


npm i -s chalk

Once installed the packages, we can add the following logic to our logger.middleware.ts file.


import { Request, Response, NextFunction } from 'express';
import { v4 as uuidv4 } from 'uuid';
import { blue, blueBright , green, red } from 'chalk';


const getProcessingTimeInMS = (time: [number, number]): string => {
  return `${(time[0] * 1000 + time[1] / 1e6).toFixed(2)}ms`
}

/**
 * add logs for an API endpoint using the following pattern
 *  [id][timestamp] method:url START processing
 *  [id][timestamp] method:url response.statusCode END processing
 * 
 * @param req Express.Request
 * @param res Express.Response
 * @param next Express.NextFunction
 */
function logger(req: Request, res: Response, next: NextFunction) {
  // generate unique identifier
  const id = uuidv4();

  // get timestamp
  const now = new Date();
  const timestamp = [
    now.getMonth() + 1,
    '-',
    now.getDate(),
    '-',
    now.getFullYear(),
    ' ',
    now.getHours(),
    ':',
    now.getMinutes(),
    ':',
    now.getSeconds()
  ].join('');

  // get api endpoint
  const { method, url } = req;

  // log start of the execution process
  const start = process.hrtime();
  const startText = green(`START:${getProcessingTimeInMS(start)}`)
  const idText = blue(`[${id}]`);
  const timeStampText = blueBright(`[${timestamp}]`);
  console.log(`${idText}${timeStampText} ${method}:${url} ${startText}`);

  // trigger once a response is sent to the client
  res.once('finish', () => {
    // log end of the execution process
    const end = process.hrtime(start);
    const endText = red(`END:${getProcessingTimeInMS(end)}`);
    console.log(`${idText}${timeStampText} ${method}:${url} ${res.statusCode} ${endText}`);
  });

  // execute next middleware/event handler
  next();
};

export default logger;

Now, we are going to open the index.ts file, import the logger middleware and use it by using app.use().

import logger from './api/middlewares/logger.middleware';

// add logger middleware
app.use(logger);

Time to Test The Logger Middleware

Go ahead and start triggering the GET api/teams endpoint. Checkout the terminal for logs.

Logger Application-Level Middleware in action

What’s Next?

So far we have covered Third-Party and Application-Level middleware. It’s time to check out how to use a router-middleware in Express.js with TypeScript.