javascript 51 lines · 9 steps

Content negotiation with res.format in Express

One Express route serves JSON, HTML, or CSV from the same data by matching the client's Accept header.

Explained by highlit
1const express = require('express');
2const router = express.Router();
3 
4router.get('/articles/:slug', async (req, res, next) => {
5 try {
6 const article = await Article.findBySlug(req.params.slug);
7 
8 if (!article) {
9 return res.format({
10 'application/json': () => res.status(404).json({ error: 'Article not found' }),
11 'text/html': () => res.status(404).render('errors/404', { slug: req.params.slug }),
12 default: () => res.status(406).send('Not Acceptable')
13 });
14 }
15 
16 const related = await article.relatedArticles({ limit: 5 });
17 
18 res.format({
19 'application/json': () => {
20 res.json({
21 data: article.toJSON(),
22 related: related.map((a) => a.toSummary())
23 });
24 },
25 
26 'text/html': () => {
27 res.render('articles/show', {
28 article,
29 related,
30 title: article.title
31 });
32 },
33 
34 'text/csv': () => {
35 res.attachment(`${article.slug}.csv`);
36 res.send(article.toCsvRow());
37 },
38 
39 default: () => {
40 res.status(406).json({
41 error: 'Not Acceptable',
42 supported: ['application/json', 'text/html', 'text/csv']
43 });
44 }
45 });
46 } catch (err) {
47 next(err);
48 }
49});
50 
51module.exports = router;
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1res.format lets one handler serve multiple representations by branching on the Accept header instead of duplicating routes.
  2. 2Always supply a default branch so unsupported Accept headers return a clean 406 rather than falling through silently.
  3. 3Wrapping async handler logic in try/catch and forwarding to next(err) routes failures into Express's error middleware.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Content negotiation with res.format in Express — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code