DEV Community

1xApi
1xApi

Posted on • Originally published at 1xapi.com

5 HTTP Edge Cases That Break APIs (And How to Fix Them)

Most API developers nail the happy path. But HTTP is a protocol with decades of baggage, and some edge cases can silently break your API in production.

Here are 5 HTTP edge cases every API developer should know about — with code examples and fixes.

1. Duplicate HTTP Headers

The HTTP spec (RFC 9110) allows multiple headers with the same name. Most frameworks merge them — but not always the way you expect.

// Express.js example
// If a client sends: X-Custom: foo AND X-Custom: bar
app.get('/test', (req, res) => {
  console.log(req.headers['x-custom']);
  // Output: 'foo, bar' (comma-joined string)
});
Enter fullscreen mode Exit fullscreen mode

The trap: If you're parsing a header value and expecting a single string, duplicate headers will silently corrupt your logic.

Fix: Always validate header values. If you expect a single value, take the first one explicitly:

const value = req.headers['x-custom']?.split(',')[0]?.trim();
Enter fullscreen mode Exit fullscreen mode

2. Empty Body on 204 No Content... or Is It?

HTTP 204 means "no content" — but nothing stops a buggy client or proxy from sending a body with it. Conversely, some frameworks accidentally attach a body to 204 responses.

// This is technically invalid but common
res.status(204).json({ message: 'deleted' }); // BAD!

// Correct
res.status(204).end();
Enter fullscreen mode Exit fullscreen mode

The trap: Some HTTP clients will throw if they try to parse a body from a 204. Others silently ignore it.

Fix: Never send a body with 204. If you need to return data after deletion, use 200 instead.

3. Transfer-Encoding: chunked vs Content-Length

When your API streams data, it uses Transfer-Encoding: chunked. But if both Content-Length AND Transfer-Encoding are present, the spec says Transfer-Encoding wins.

HTTP/1.1 200 OK
Content-Length: 50
Transfer-Encoding: chunked

# The client SHOULD ignore Content-Length
Enter fullscreen mode Exit fullscreen mode

The trap: Some proxies strip Transfer-Encoding but keep Content-Length, causing truncated responses.

Fix: Never set both. If streaming, let your framework handle Transfer-Encoding and omit Content-Length:

app.get('/stream', (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  // Don't set Content-Length when streaming!
  stream.pipe(res);
});
Enter fullscreen mode Exit fullscreen mode

4. HEAD Requests Must Match GET (But Return No Body)

A HEAD request should return the exact same headers as a GET — including Content-Length — but with an empty body. Many APIs get this wrong.

// Common mistake: different response for HEAD
app.head('/api/users', (req, res) => {
  res.status(200).end(); // Missing Content-Length!
});

// Correct: compute the same response, skip the body
app.head('/api/users', async (req, res) => {
  const users = await getUsers();
  const body = JSON.stringify(users);
  res.set('Content-Length', Buffer.byteLength(body));
  res.status(200).end();
});
Enter fullscreen mode Exit fullscreen mode

The trap: CDNs and caches use HEAD to validate cached responses. If your HEAD and GET headers don't match, caching breaks silently.

5. The 301 Redirect Method Switch

When a client receives a 301 Moved Permanently redirect, browsers historically change the method from POST to GET. Your POST data disappears.

# Client sends POST /old-endpoint
# Server responds: 301 Location: /new-endpoint
# Browser follows up with: GET /new-endpoint  <-- METHOD CHANGED!
Enter fullscreen mode Exit fullscreen mode

Fix: Use 307 Temporary Redirect or 308 Permanent Redirect — these preserve the original HTTP method:

app.post('/old-endpoint', (req, res) => {
  res.redirect(308, '/new-endpoint'); // POST stays POST
});
Enter fullscreen mode Exit fullscreen mode

Quick Reference

Edge Case Risk Fix
Duplicate headers Corrupted values Split and take first
204 with body Client parsing errors Never send body on 204
Chunked + Content-Length Truncated responses Use one, not both
HEAD ≠ GET headers Broken caching Match headers exactly
301 method switch Lost POST data Use 307/308 instead

Wrapping Up

HTTP seems simple until it isn't. These edge cases don't show up in tutorials, but they'll bite you in production — especially when proxies, CDNs, and diverse clients enter the picture.

Bookmark this as a quick reference. Your future self debugging a mysterious production issue will thank you.


Building APIs? Check out 1xAPI for production-ready API tools and services.

Top comments (0)