Instructing Cloudflare to cache my page with HTTP headers instead of Page Rules

I’ve read a lot of support documents that made me think this should be possible, however I can’t seem to make it work. My google-fu is also failing me.

I have a page that I render on the server that I want Cloudflare to cache. Currently we instruct Cloudflare to cache it using Page Rules. I would like to be able to do this with HTTP headers instead to make maintenance easier (in other words: so we can do it in code).

According to this support document I think I’m satisfying all the conditions:

  • If the Cache-Control header is set to private , no-store , no-cache , or max-age=0 , or if there is a cookie in the response, then Cloudflare does not cache the resource.
  • Otherwise, if Cache-Control is set to public and the max-age is greater than 0 , or if the Expires header is a date in the future, Cloudflare caches the resource.

In my case Cache-Control is set to public, there is no max-age and I’m not setting a cookie.

Response headers when hitting my server directly:

HTTP/2 200
cache-control: public, max-age=3600
content-length: 4
content-type: text/plain; charset=utf-8
date: Tue, 06 Jul 2021 13:56:01 GMT
server: Cowboy
x-request-id: Fo84LkphiPA1z7MAAnjh

Response headers when hitting my server through Cloudflare:

HTTP/1.1 200 OK
Date: Tue, 06 Jul 2021 13:40:43 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 4
Connection: keep-alive
Cache-Control: public, max-age=3600
X-Request-Id: Fo83WGXdy4g_THoAAYCE
CF-Cache-Status: DYNAMIC
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v2?s=82Hdx4gOOgV%2FioqoROOkiaA7J0SCvTZFerAOYDMdc9HjZhwaHUcYCRQdyhVH%2B1f8Ploo%2BEEf968176Ko9H%2FeMWZWQ638VcPOAkaWsG8YWY7RRuo3angLKozqdtJ1ChKUNacCxqE%3D"}],"group":"cf-nel","max_age":604800}
NEL: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
CF-RAY: 66a93f0a3c912c26-FRA
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400

I’m always getting CF-Cache-Status: DYNAMIC.

By default, Cloudflare will only cache certain file extensions. If it is not one of those listed, you need a matching “Cache Everything” page rule.

2 Likes

I would argue that paragraph is at least confusing if not misleading.

Cloudflare only caches based on file extension and doesn’t cache by MIME type.

and

The Cloudflare CDN automatically caches files containing certain file extensions and doesn’t cache HTML by default

So what does HTML in the second paragraph mean? Does it refer to the extension in the URL or the Content-Type (the first sentence says the MIME type doesn’t matter, does that apply to the HTTP header?).

It is just repeating and reiterating that HTML (which is generally URLs with file extension .html, .htm, .php, .asp, .aspx, / etc.) is not cached by default.

It says Cloudflare does not cache by MIME type. There are cases (for example) where people serve images with funny file extensions, but set the correct Content-Type and Cache-Control headers expecting that “Cloudflare cache JPEG files”. CF will only cache by default if the file extension is one of those listed.

Essentially, there are two branches used to service requests. One goes through the Cloudflare cache, and the other does not. The default logic says that the listed file extensions go through the cache, otherwise the cache is bypassed. That decision is made on the request, not on the response. At the point in time a request is received the MIME type is unknown, so MIME cannot be used to make a decision. A Cache-Level page rule can change that default request decision to include or exclude certain requests based on the URL.

That means your requests are not going down the cache branch, and you need a Page Rule to force that path to be used.

You’re using wrong header instead of cache-control, use either cdn-cache-control or cloudflare-cdn-cache-control see https://blog.cloudflare.com/cdn-cache-control/ and @michael mention of Understanding Cloudflare's CDN – Cloudflare Help Center still applies

That makes sense, thanks for the exhaustive explanation. :+1: Hoping some of this extra details makes it into the support document at some point.

This is definitely not true according to my testing.

HTTP/1.1 200 OK
Date: Thu, 08 Jul 2021 07:41:05 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 4
Connection: keep-alive
Cache-Control: max-age=0, private, must-revalidate
Cdn-Cache-Control: public, max-age=120
X-Request-Id: Fo_A4aBRc7D89dkAAizD
CF-Cache-Status: DYNAMIC
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v2?s=lxlDh1YN97IN3ek2%2BfzJiOSA7XE2O5hPn8eEPncQh6xog%2BCfJUNKACfG%2F1IFlTW1%2FHBLgm83t27LrUbO3yVBVrk5chLpt8eAnfdWeR2msn2J0ivUTpvUM87EOZjdnvOuGztdPZA%3D"}],"group":"cf-nel","max_age":604800}
NEL: {"report_to":"cf-nel","max_age":604800}
Server: cloudflare
CF-RAY: 66b7ab0d9dab062d-FRA
alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400

You can see cdn-cache-control is set but cf-cache-status is DYNAMIC.

It is in one of the support docs, somewhere!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.