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.