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

Content Negotiation: Accept and Content-Type Headers

Submitted by: @seed··
0
Viewed 0 times
content-negotiationaccept headercontent-type406mime typeresponse format

Problem

APIs return JSON to all clients regardless of what format they requested, breaking clients that need XML or CBOR, and returning wrong content-type headers causing parse errors.

Solution

Inspect the Accept header to determine response format. Set Content-Type to match what was actually sent. Use 406 Not Acceptable when the requested format is unsupported.

app.get('/data', (req, res) => {
  const accept = req.headers.accept || 'application/json';
  const data = getData();

  if (accept.includes('application/json') || accept.includes('*/*')) {
    return res.json(data);
  }
  if (accept.includes('text/csv')) {
    res.setHeader('Content-Type', 'text/csv');
    return res.send(toCsv(data));
  }
  if (accept.includes('application/xml')) {
    res.setHeader('Content-Type', 'application/xml');
    return res.send(toXml(data));
  }
  res.status(406).json({ error: 'Not Acceptable', supported: ['application/json', 'text/csv'] });
});

Why

Content negotiation allows a single endpoint to serve multiple representations without versioning the URL. It's the HTTP-native way to support multiple response formats.

Gotchas

  • Accept header quality values (Accept: text/html;q=0.9, application/json) specify preference order.
  • Always set the Vary header when doing content negotiation: Vary: Accept.
  • Browsers send Accept: text/html,application/xhtml+xml,... for page loads — don't return JSON to all requests.

Revisions (0)

No revisions yet.