0

My backend application sends Cache-Control headers so that NGINX and the browser can cache responses.

I would like CloudFlare to not cache these responses. This is because they may have non-public information and while NGINX is cookie-aware when caching, CloudFlare is not (at least not on the free or pro plan)

Essentially I want NGINX to see this so that it caches the response:

Cache-Control: public, max-age=x (This is what my backend app sends)

And for CloudFlare and the browser to see: (So the browser caches the response, but CloudFlare wont because it is private)

Cache-Control: private, max-age=x

e.g. CloudFlare should always MISS on these requests, but possibly HIT when it gets to nginx.

I think this could be accomplished if NGINX could replace "public" with "private", or recreate the header is the "max-age" variable could be captured. It could also be done if my app sends "private", but NGINX is instructed to cache private responses anyways. I have not been able to find a way to do either however.

Cyral
  • 101

2 Answers2

0

OK, this turns out to be quite easy: nginx already has a directive to ignore the upstream Cache-Control and Set-Cookie headers sent by the web app when deciding whether to cache, proxy_ignore_headers.

proxy_ignore_headers Cache-Control Set-Cookie;

This also requires that a cache lifetime be set with proxy_cache_valid, for example:

proxy_cache_valid any 1d;

So after this you can (and should) just send Cache-Control: private; ... from your web app, and nginx will cache but downstream caches like CloudFlare will not.

Note that your proxy_cache_key needs some way to differentiate responses sent to different users with the same URL, otherwise one user may see another user's data.

For a lot more information, be sure to read NGINX's Guide to Caching.

Michael Hampton
  • 252,907
0

I ended up with a solution that feels a bit hacky, but it works.

It uses regex inside a map to replace "public" with "private" in the Cache-Control header.

map $upstream_http_cache_control $cachemap {
  ~(public)(.*)  private$2;
  default "";
}

...

proxy_hide_header 'Cache-Control'; add_header Cache-Control $cachemap always;

Cyral
  • 101