javascript 61 lines · 10 steps

Sharing route logic with router.param in Express

An Express router centralizes article loading and authorization so each route handler stays tiny and focused.

Explained by highlit
1const express = require('express');
2const createError = require('http-errors');
3const { Article } = require('../models');
4 
5const router = express.Router();
6 
7router.param('articleId', async (req, res, next, id) => {
8 try {
9 const article = await Article.findByPk(id, {
10 include: ['author', 'tags'],
11 });
12 
13 if (!article) {
14 return next(createError(404, 'Article not found'));
15 }
16 
17 req.article = article;
18 res.locals.article = article;
19 next();
20 } catch (err) {
21 next(err);
22 }
23});
24 
25const requireAuth = (req, res, next) => {
26 if (!req.user) return next(createError(401, 'Authentication required'));
27 next();
28};
29 
30const requireOwnership = (req, res, next) => {
31 if (req.article.authorId !== req.user.id) {
32 return next(createError(403, 'You do not own this article'));
33 }
34 next();
35};
36 
37const editorChain = [requireAuth, requireOwnership];
38 
39router.get('/:articleId', (req, res) => {
40 res.json(req.article.toPublicJSON());
41});
42 
43router.patch('/:articleId', editorChain, async (req, res, next) => {
44 try {
45 await req.article.update(req.body, { fields: ['title', 'body', 'status'] });
46 res.json(req.article.toPublicJSON());
47 } catch (err) {
48 next(err);
49 }
50});
51 
52router.delete('/:articleId', editorChain, async (req, res, next) => {
53 try {
54 await req.article.destroy();
55 res.status(204).end();
56 } catch (err) {
57 next(err);
58 }
59});
60 
61module.exports = router;
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1router.param runs once per matching route to preload and validate a resource before any handler executes.
  2. 2Composing named middleware into a reusable array keeps authentication and ownership checks consistent across routes.
  3. 3Passing errors to next() lets a central error handler manage every failure path uniformly.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Sharing route logic with router.param in Express — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code