Posted by thisisfatih 16 hours ago
The classic problem here is if you do that thing where user agents that send "accept: text/html" get HTML, while user agents that don't get JSON or some other format.
This used to be impossible to deploy behind Cloudflare caching, because they ignored the Vary header on anything other than images - so you risked caching the JSON version and then serving it up to someone who was expecting HTML.
(Independent of the Cloudflare feature I ended up deciding never to use that pattern, because I prefer having URL that predictably returns HTML or JSON - I add a .json suffix to my apps to serve JSON instead.)
If you're versioning the whole API though, I agree it's best behind a a /v2/ prefix.
https://blog.cloudflare.com/enterprise-grade-features-for-al...
Like Prefetch: https://developers.cloudflare.com/speed/optimization/content...
I’d say that it forces you to maybe parse and understand the headers that vary header.
Accept-Language is supposed to be parsed and matched according to RFC4647 in one of 3 ways. That part is rather complex, but it’s not Vary’s fault.
I'm not sure if it is possible to solve this nicely in a generic way, but it does make it a bit ugly.
[0] Okay, my claim is only definite up to my memory of using Cloudflare for a fairly high-traffic circa 2019-2022. I haven't used Cloudflare after that point, but a quick search of their docs shows support
The point of a reverse proxy is to reduce load on the server rendering the page. If you GET, the page is rendered. So in order for etag/last-modified to be effective, the CMS must implement HEAD. If the CMS doesn't implement HEAD or implements it in a way that ends up doing all the work of GET anyway, you just end up with more load than just doing a GET every time.
The funny thing is that the way HTTP is designed the simplest PHP script can do this correctly, because the server must send the headers first, so a PHP script can NOT do the work to generate the HTML until it has sent the correct headers, as they won't be able to change the headers after they start sending the body. In theory, the process could just shut down the instant the first body byte starts being sent and save work in a HEAD request. The problem is that pretty much everything works in a more "clever" way: you have some sort of template engine that generates the whole HTML, a view method that makes the DB calls, etc., and only after all the work is done the HTTP headers are sent. Because this method allows the backend to add/change/remove headers at any point during the process, not just at the start.
Essentially the problem is that CF doesn't know what your server is running, and even an s-maxage=60 is going to look like a bug from the user's perspective if they go to /post?id=123, navigate to /edit-post?id=123, edit the post, go back to /post?id=123 and see the post unchanged.
And, of course, you can still use cache-control to permit some duration of staleness, so that you don’t literally revalidate on every request.
No, you just implement GET properly so that nothing gets "rendered" for 304 Not Modified responses.
Wow, sometimes I think it's amazing the web works at all!
We generate custom content for a given authentication context. We definitely want caching at the user agent, but we want the cache keyed by the authenticated identity. Otherwise something like logging out and logging in as a different identity can produce monstrously confused results when an SPA or similar mixes some cached and some fresh responses into one page.
I'm sure most people here already knows the joke, but for the lucky 10,000, here's the full joke:
There are only two hard problems in computer science. Naming things, cache invalidation, and off-by-one errors.
Although its not clear from the article itself, my gut feeling is that some big enough client arm twisted them to support it before they sign the contract again
"If one response omits it, Cloudflare could cache that response without the variance needed to keep it isolated."[2]
Will that non-Vary cache object front-run any Vary-segmented cache objects?
If so, probably worth adding a snippet rule to ensure every response has a Vary header?
1: https://developers.cloudflare.com/cache/concepts/vary/#how-v...
2: https://blog.cloudflare.com/vary-support/#how-a-response-mov...
I actually assumed when I started using Cloudflare that it did have vary support and it led to a serious bug in my sass app at the time.
But we can't cache those dynamic pages since they vary based on accept language. Maybe with this we can
Actual real content negotiation in 2026. Never thought I'd live to see the day.