Or why Accept headers mattered more than it seemed
Recently, while debugging a seemingly simple API call made with JavaScript’s fetch()
function, I encountered an issue that led me down a rabbit hole of HTTP protocol differences, CloudFlare behavior, and header validation strictness. What started as a “works in Postman, fails in my app” scenario turned into a discovery about how HTTP/2 and HTTP/1.1 are handled differently by CloudFlare and still remains a mistery why it happened.
The Problem
The issue manifested as a CloudFlare-generated 415 Unsupported Media Type error when making API calls from a mobile application, while the identical request worked perfectly through Postman (web based). Here’s the JavaScript code that was failing:
await fetch(API.login, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: email,
password: password,
}),
});
The response headers clearly showed CloudFlare was intercepting the request:
Content-Type: text/html
Server: cloudflare
Instead of reaching the backend API, CloudFlare was returning an HTML error page with “415 Unsupported Media Type.”
The Investigation: Isolating Variables
Through systematic testing, I discovered the key difference: HTTP protocol version.
- Postman (working): HTTP/1.1
- Mobile app (failing): HTTP/2
When I configured Postman to use HTTP/2, it immediately started producing the same 415 error. This confirmed that the protocol version was the culprit, not the request content itself.
The Root Cause: “Accept” Header Validation
The breakthrough came through methodical header elimination in Postman’s HTTP/2 mode. By disabling default headers one by one, I discovered that the Accept
header was the problematic element.
The failing scenario:
Accept: */* (Postman's default)
The working solution:
Accept: application/json
Why This Happens?
The research reveals that this isn’t necessarily a bug, but rather a consequence of how different systems handle HTTP/2 requests compared to HTTP/1.1. To be honest I haven’t found anywhere a single documentation that says that Accept
header need to be used with specific values and not the wild card for HTTP/2
protocols. This could be some security setting coming from CloudFlare that I wasn’t awear of, or just how the CloudFlare is configured. I didn’t found any explicit documentation that has this as a rule for the usage of the Accept
header and the RFC 7231 documentation doesn’t have anything on that topic.