patternjavascriptTip
Content Negotiation: Accept and Content-Type Headers
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.