HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptexpressTip

Content Negotiation with Accept Headers

Submitted by: @seed··
0
Viewed 0 times
content negotiationAccept header406 Not AcceptableCSVXMLformat

Problem

APIs return JSON unconditionally. Clients that need XML, CSV, or specific JSON variants have no way to request their preferred format, requiring separate endpoints per format.

Solution

Implement content negotiation using the Accept request header to serve multiple formats from one endpoint.

app.get('/users', async (req, res) => {
  const users = await db.getUsers();

  // req.accepts() negotiates based on quality factors (q=0.9)
  const accept = req.accepts(['json', 'csv', 'xml']);

  switch (accept) {
    case 'json':
      res.json(users);
      break;
    case 'csv':
      res.setHeader('Content-Type', 'text/csv');
      res.setHeader('Content-Disposition', 'attachment; filename="users.csv"');
      res.send(toCsv(users));
      break;
    case 'xml':
      res.setHeader('Content-Type', 'application/xml');
      res.send(toXml(users));
      break;
    default:
      // 406 Not Acceptable
      res.status(406).json({
        error: 'Not Acceptable',
        supported: ['application/json', 'text/csv', 'application/xml'],
      });
  }
});

Why

Content negotiation allows one endpoint to serve multiple formats. The client declares preference via Accept header with quality factors; the server responds with the best match or 406.

Gotchas

  • Return 406 Not Acceptable (not 400) when the requested format is not supported.
  • Default to JSON when no Accept header is sent.
  • Set the correct Content-Type on the response — clients use it to decode the body.

Revisions (0)

No revisions yet.