An Express router provides a subset of Express methods. To create an instance of one, we invoke the .Router() method on the top-level Express import.
To use a router, we mount it at a certain path using app.use() and pass in the router as the second argument. This router will now be used for all paths that begin with that path segment. To create a router to handle all requests beginning with /monsters, the code would look like this:
const express = require('express');
const app = express();
const monsters = {
'1': {
name: 'godzilla',
age: 250000000
},
'2': {
Name: 'manticore',
age: 21
}
}
const monstersRouter = express.Router();
app.use('/monsters', monstersRouter);
monstersRouter.get('/:id', (req, res, next) => {
const monster = monsters[req.params.id];
If (monster) {
res.send(monster);
} else {
res.status(404).send();
}
});
Inside the monsterRouter, all matching routes are assumed to have /monsters prepended, as it is mounted at that path. monstersRouter.get('/:id') matches the full path /monsters/:id.
When a GET /monsters/1 request arrives, Express matches /monsters in app.use() because the beginning of the path ('/monsters') matches. Express' route-matching beginning of the path ('monsters') matches.
When a GET /monsters/1 request arrives, Express matches /monsters in app.use() because the beginning of the path ('/monsters') matches. Express’ route-matching algorithm enters the monstersRouter‘s routes to search for full path matches. Since monstersRouter.get('/:id) is mounted at /monsters, the two paths together match the entire request path (/monsters/1), so the route matches and the callback is invoked. The 'godzilla' monster is fetched from the monster array and sent back.
const express = require('express');
const app = express();
const { getElementById, getIndexById, updateElement,
seedElements, createElement } = require('./utils');
const PORT = process.env.PORT || 4001;
// Use static server to serve the Express Yourself Website
app.use(express.static('public'));
const expressions = [];
seedElements(expressions, 'expressions');
const animals = [];
seedElements(animals, 'animals');
const expressionsRouter = express.Router();
app.use('/expressions', expressionsRouter);
// Get all expressions
expressionsRouter.get('/', (req, res, next) => {
res.send(expressions);
});
// Get a single expression
app.get('/expressions/:id', (req, res, next) => {
const foundExpression = getElementById(req.params.id, expressions);
if (foundExpression) {
res.send(foundExpression);
} else {
res.status(404).send();
}
});
// Update an expression
app.put('/expressions/:id', (req, res, next) => {
const expressionIndex = getIndexById(req.params.id, expressions);
if (expressionIndex !== -1) {
updateElement(req.params.id, req.query, expressions);
res.send(expressions[expressionIndex]);
} else {
res.status(404).send();
}
});
// Create an expression
app.post('/expressions', (req, res, next) => {
const receivedExpression = createElement('expressions', req.query);
if (receivedExpression) {
expressions.push(receivedExpression);
res.status(201).send(receivedExpression);
} else {
res.status(400).send();
}
});
// Delete an expression
app.delete('/expressions/:id', (req, res, next) => {
const expressionIndex = getIndexById(req.params.id, expressions);
if (expressionIndex !== -1) {
expressions.splice(expressionIndex, 1);
res.status(204).send();
} else {
res.status(404).send();
}
});
// Get all animals
app.get('/animals', (req, res, next) => {
res.send(animals);
});
// Get a single animal
app.get('/animals/:id', (req, res, next) => {
const animal = getElementById(req.params.id, animals);
if (animal) {
res.send(animal);
} else {
res.status(404).send();
}
});
// Create an animal
app.post('/animals', (req, res, next) => {
const receivedAnimal = createElement('animals', req.query);
if (receivedAnimal) {
animals.push(receivedAnimal);
res.status(201).send(receivedAnimal);
} else {
res.status(400).send();
}
});
// Update an animal
app.put('/animals/:id', (req, res, next) => {
const animalIndex = getIndexById(req.params.id, animals);
if (animalIndex !== -1) {
updateElement(req.params.id, req.query, animals);
res.send(animals[animalIndex]);
} else {
res.status(404).send();
}
});
// Delete a single animal
app.delete('/animals/:id', (req, res, next) => {
const animalIndex = getIndexById(req.params.id, animals);
if (animalIndex !== -1) {
animals.splice(animalIndex, 1);
res.status(204).send();
} else {
res.status(404).send();
}
});
app.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
const express = require('express');
const app = express();
const { getElementById, getIndexById, updateElement,
seedElements, createElement } = require('./utils');
const PORT = process.env.PORT || 4001;
// Use static server to serve the Express Yourself Website
app.use(express.static('public'));
let animals = [];
seedElements(animals, 'animals');
const expressionsRouter = require('./expressions.js');
app.use('/expressions', expressionsRouter);
// Get a single expression
app.get('/expressions/:id', (req, res, next) => {
const foundExpression = getElementById(req.params.id, expressions);
if (foundExpression) {
res.send(foundExpression);
} else {
res.status(404).send();
}
});
// Update an expression
app.put('/expressions/:id', (req, res, next) => {
const expressionIndex = getIndexById(req.params.id, expressions);
if (expressionIndex !== -1) {
updateElement(req.params.id, req.query, expressions);
res.send(expressions[expressionIndex]);
} else {
res.status(404).send();
}
});
// Create an expression
app.post('/expressions', (req, res, next) => {
const receivedExpression = createElement('expressions', req.query);
if (receivedExpression) {
expressions.push(receivedExpression);
res.status(201).send(receivedExpression);
} else {
res.status(400).send();
}
});
// Delete an expression
app.delete('/expressions/:id', (req, res, next) => {
const expressionIndex = getIndexById(req.params.id, expressions);
if (expressionIndex !== -1) {
expressions.splice(expressionIndex, 1);
res.status(204).send();
} else {
res.status(404).send();
}
});
// Get all animals
app.get('/animals', (req, res, next) => {
res.send(animals);
});
// Get a single animal
app.get('/animals/:id', (req, res, next) => {
const animal = getElementById(req.params.id, animals);
if (animal) {
res.send(animal);
} else {
res.status(404).send();
}
});
// Create an animal
app.post('/animals', (req, res, next) => {
const receivedAnimal = createElement('animals', req.query);
if (receivedAnimal) {
animals.push(receivedAnimal);
res.status(201).send(receivedAnimal);
} else {
res.status(400).send();
}
});
// Update an animal
app.put('/animals/:id', (req, res, next) => {
const animalIndex = getIndexById(req.params.id, animals);
if (animalIndex !== -1) {
updateElement(req.params.id, req.query, animals);
res.send(animals[animalIndex]);
} else {
res.status(404).send();
}
});
// Delete a single animal
app.delete('/animals/:id', (req, res, next) => {
const animalIndex = getIndexById(req.params.id, animals);
if (animalIndex !== -1) {
animals.splice(animalIndex, 1);
res.status(204).send();
} else {
res.status(404).send();
}
});
app.listen(PORT, () => {
console.log(`Server is listening on ${PORT}`);
});
const express = require('express');
const { seedElements, getElementById, createElement, updateElement, getIndexById } = require('./utils');
let expressions = [];
seedElements(expressions, 'expressions');
const expressionsRouter = express.Router();
module.exports = expressionsRouter;
// Get all expressions
expressionsRouter.get('/', (req, res, next) => {
res.send(expressions);
});

Matching In Nested Routers
As you saw in the previous exercise, when using routers, it’s important to remember that the full path of a request can be segmented.
In the diagram to the left, you can create an Express application using two routers. A GET request arrives for /expressions/1. Because the beginning of the path does not match /animals in the first app.use(), the Express server moves on to the next app.use(), which matches /expressions.
Express’ route matching algorithm then enters the expressionsRouterinstance which is required from expressions.js. Inside this router, the path matching changes. Even though the whole request path is /expressions/1, inside the expressionsRouter, all paths are matched from the parts of the path after /expressions, meaning that in this context, the router is trying to match the path /1.
Because the path is /1, the path does not match the first .get() method at /. The Express server moves on to the next route, which has a route parameter of /:id, so it matches! This route handles the necessary logic and sends the response.
Routers can be nested as many times as necessary for an application, so understanding nested route matching is important for created complicated APIs.