How to Use Router-Level Middleware in Express.js using 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 is a Router-Level Middleware?

If you understand how application-level middleware works, you will understand router-level middleware because both work the same way. The only difference is how they are bound.

The application-level middleware, as explained in How to Use Application-Level Middleware with Express.js and TypeScript, is bound to the whole application.

On the other hand, a router-level middleware is bound to an instance of a router or Express.router(). This means the middleware will be applied to only the API endpoints defined in a specific instance of Express.router(). That being said, a router-middleware would execute additional logic in a file like teams.routes.ts, which contains only /api/teams related API endpoints.

const router = Router();

router
  .route('/')
  .get(
    Controller.getTeams
  );

router
  .route('/:id')
  .get(
    Controller.getTeamById
  );

router
  .route('/')
  .post(
    Controller.addTeam
  );

router
  .route('/:id')
  .patch(
    Controller.updateTeamById
  );

router
  .route('/:id')
  .delete(
    Controller.deleteTeamById
  );

export default router;

Note: Currently, the teams.routes.ts file doesn’t have router-level middleware. We show the code to help you visualize how router-level middleware can be applied to a dedicated set of routes.

How to create a Router-Level Middleware in Express.js using TypeScript?

Since router-middlewares are bound to an Express.router() instance, we need to ensure there is an instance of it. Typically, this looks something like this:

import { Router } from 'express';

const router = Router();

An instance of Express.router() has a use() method, which you can also find when you have an instance of Express(). Using the use() method allows adding a middleware function:

router.use(
  routerLevelMiddleware()
);

In this way, routerLevelMiddleware() will trigger to any of the endpoints tied to that router. For example, if there we have the following snippet of code.

router.route('/endpoint1').get(myEndpoint1Function());
router.route('/endpoint2').get(myEndpoint2Function());
router.route('/endpoint3').get(myEndpoint3Function());
router.route('/endpoint4').get(myEndpoint4Function());

The routerLevelMiddleware() will be triggered before triggering any of the following endpoints:

  • GET /endpoint1
  • GET /endpoint2
  • GET /endpoint3
  • GET /endpoint4

or in other words, it will trigger before any of the following request handlers

  • myEndpoint1Function()
  • myEndpoint2Function()
  • myEndpoint3Function()
  • myEndpoint4Function()

It is also possible to add router-middleware to only a single API endpoint. To do so, add the middleware function as an argument of any of the route matcher functions provided by the router.

Route matchers are methods in Express.js defining the HTTP method (GET, POST, PUT, DELETE, PATCH, TRACE, OPTIONS, HEAD, CONNECT) of an endpoint. Therefore, whenever you use any of the following methods

  • get()
  • post()
  • put()
  • patch()
  • delete()
  • trace()
  • head()
  • connect()

which you can see implemented in the following way:

router.route('/').get();
router.route('/').post();
router.route('/').put();
router.route('/').patch();
router.route('/').delete();
router.route('/').trace();
router.route('/').options();
router.route('/').head();
router.route('/').connect();

You can add the middleware function as the first argument for those functions, and then set the request handler.

router.route('/').get(routerLevelMiddleware(), myEndpoint1Function());

What’s Next?

In this section, we explained how to create router-level middleware, which resembles application-level middleware. If you have been working on the Learn How to Use TypeScript With Node.js and Express.js series, you noticed we didn’t implement any router-middleware to the project in this article. However, I considered it best to have a separate post dedicated to adding an authentication middleware, which will be used as a router-middleware.

Did you like this article?

Share your thoughts by replying on Twitter of Become A Better Programmer or to my personal Twitter account.