Cloudflare’s Early Hints “Optimization” sends the “nginx-ssl early hints” to a part of my website that is not reference by any preconnect header.
A request through Cloudflare such as: curl https://example.com/api/sample
Will return two requests to the nginx webserver at the same exact time.
162.158.87.31 - - [09/Apr/2023:12:16:16 +0000] “GET /api/sample HTTP/1.1” 502 166 “https://example.org/” “curl/7.81.0”
162.158.87.31 - - [09/Apr/2023:12:16:16 +0000] “GET /api/sample HTTP/1.1” 502 166 “-” “nginx-ssl early hints”
Is there any fix to this or is this a bug?
Turning off early hints seems to work but I would like it to remain enabled.
Early Hints is a ON/OFF feature. The API does not have any endpoint where you can tinker any more than enabling/disabling it for a given zone (domain and subdomain).
From the documentation:
Note
Early Hints is currently only supported over HTTP/2 and HTTP/3.
Early Hints are only generated and cached:
For URIs with .html, .htm, or .php file extensions, or no file extension
On 200, 301, or 302 response return codes
When the response contains link headers with preconnect or preload rel types, such as Link: </img/preloaded.png>; rel=preload
Since response code and link headers will only be known too late in the process, that leaves us with a couple of possible workarounds, if disabling Early Hints for your API is a must (other than, perhaps, a Cloudflare Worker):
Disable HTTP/2 and HTTP/3 on the Network panel of Cloudflare dashboard; which is bad because it will impact your site’s speed, as well as because it’s documented as a temporary limitation; or
Rename your API paths so that it contains a file extension other than .html, .htm or .php (for instance, /api/sample.json, or /api/sample.txt), not necessarily desirable given other collateral effects (content-type, CORS policy etc.).
If you have full control over the API origin server, why not program it to not return the preload/preconnect headers under certain request types? So a simple one would be if useragent of the request to /api/sample contains curl remove or do not add a preload/preconnect header.
cbrant is correct. the api does not return any headers other than those that are required for http/1.0, so content type, length, status, etc. The solution is to either ignore the early hints to the api or provide it with a different extension