Categories
Express JavaScript Nodejs

Guide to the Express Router Object — Multiple Requests and Middleware

Spread the love

The Expressrouter object is a collection of middlewares and routes. It a mini-app within the main app.

It can only perform middleware and routing functions and can’t stand on its own. It also behaves like middleware itself, so we can use it with app.use or as an argument to another route’s use method.

In this article, we’ll look at the router object’s methods, including route and use.

Methods

router.route(path)

We can use router.route to handle multiple kinds of requests with one chain of function calls.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.route('/')  
  .all((req, res, next) => {  
    next()  
  })  
  .get((req, res, next) => {  
    res.send('foo');  
  })  
  .put((req, res, next) => {  
    next();  
  })  
  .post((req, res, next) => {  
    next();  
  })  
  .delete((req, res, next) => {  
    next();  
  })
app.use('/foo', router);  
app.listen(3000);

Then when we make a GET request to /foo, we get foo.

We can also write something like:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.route('/')  
  .all((req, res, next) => {  
    console.log('all requests');  
    next();  
  })  
  .get((req, res, next) => {  
    console.log('get request');  
    res.send('foo');  
    next();  
  })  
  .put((req, res, next) => {  
    console.log('put request');  
    res.send('put');  
    next();  
  })  
  .post((req, res, next) => {  
    console.log('post request');  
    res.send('post');  
    next();  
  })  
  .delete((req, res, next) => {  
    console.log('delete request');  
    res.send('delete');  
    next();  
  })
app.use('/foo', router);  
app.listen(3000);

Then when a GET, POST, PUT or DELETE requests are made to /foo, then we get the corresponding response.

The middleware ordering is based on when the route is created and not when the handlers are added to the route.

router.use([path], [function, …] function)

The router.use method lets us add one or more middleware functions with an optional mount path, which defaults to /.

It’s similar to app.use, except it’s applied to the router object instead of the whole app.

For example, if we have:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.use((req, res, next) => {  
  console.log('router middleware called');  
  next();  
})
router.get('/', (req, res) => {  
  res.send('foo');  
})
app.get('/', (req, res) => {  
  res.send('hi');  
})
app.use('/foo', router);  
app.listen(3000);

Then we get router middleware called when we make a GET request to the /foo path since we’re going through the router middleware to do that.

On the other hand, if we make a GET request to /, we don’t get that message logged since we aren’t using the router object to handle that request.

This means that attaching a middleware to the router object let us do something before a route that’s handled router object is handled.

We can also chain multiple middlewares as comma-separated list of middlewares, an array of middlewares or both together.

For example, we can write:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
const mw1 = (req, res, next) => {  
  console.log('mw1 called');  
  next();  
}
const mw2 = (req, res, next) => {  
  console.log('mw2 called');  
  next();  
}
const mw3 = (req, res, next) => {  
  console.log('mw3 called');  
  next();  
}
router.use([mw1, mw2], mw3);
router.get('/', (req, res) => {  
  res.send('foo');  
})
app.use('/foo', router);  
app.listen(3000);

Then all 3 middlewares, mw1 , mw2 , and mw3 all get run, so we get:

mw1 called  
mw2 called  
mw3 called

logged if we make a GET request to /foo .

We can also specify a path for the middleware. If it’s specified, then only request made to the specified path is handled.

For example, if we have:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.use('/bar', (req, res, next) => {  
  console.log('middlware called');  
  next();  
});
router.get('/bar', (req, res) => {  
  res.send('bar');  
})
router.get('/', (req, res) => {  
  res.send('foo');  
})
app.use('/foo', router);  
app.listen(3000);

Then when a GET request is made to /foo/bar , then our middleware is called, so we get middleware called in this case.

If we make a GET request to /foo , then our middleware doesn’t get called.

We can also pass in a pattern or regex for the path that we pass into use .

For example, we can write:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.use('/ab?c', (req, res, next) => {  
  console.log('middlware called');  
  next();  
});
router.get('/ab?c', (req, res) => {  
  res.send('bar');  
})
app.use('/foo', router);  
app.listen(3000);

Then when we make a GET request to /foo/abc , we get middleware called logged. We get the same result with /foo/ac .

We can pass in a regex as the path as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();  
const router = express.Router();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
router.use('/a(bc)?$', (req, res, next) => {  
  console.log('middlware called');  
  next();  
});
router.get('/a(bc)?$', (req, res) => {  
  res.send('bar');  
})
app.use('/foo', router);  
app.listen(3000);

Then when we make a GET request to /foo/abc or /foo/a , we get middleware called logged.

Conclusion

We can handle multiple kinds of requests in a router object with the route method. It lets us chain a series of method calls and pass in route handlers for each kind of request.

With the use method, we can pass in middleware that only applies to routes handled by the router object. Any other route won’t invoke the middleware.

We can pass in a string or regex path to the use method to only handle requests that are made to certain paths.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *