使用 nginx 和浏览器缓存响应,但不使用 CloudFlare

使用 nginx 和浏览器缓存响应,但不使用 CloudFlare

我的后端应用程序发送 Cache-Control 标头,以便 NGINX 和浏览器可以缓存响应。

我希望 CloudFlare 不要缓存这些响应。这是因为它们可能包含非公开信息,并且尽管 NGINX 在缓存时能够识别 cookie,但 CloudFlare 却不能(至少在免费版或专业版中不能)

本质上我希望 NGINX 看到这一点,以便它缓存响应:

Cache-Control: public, max-age=x(这是我的后端应用程序发送的内容)

CloudFlare 和浏览器可以看到:(因此浏览器会缓存响应,但 CloudFlare 不会,因为它是私有的)

Cache-Control: private, max-age=x

例如,CloudFlare 应该总是会错过这些请求,但当到达 nginx 时可能会命中。

我认为,如果 NGINX 可以将“public”替换为“private”,或者重新创建标头(如果可以捕获“max-age”变量),则可以实现这一点。如果我的应用程序发送“private”,但 NGINX 被指示缓存私有响应,也可以做到这一点无论如何。然而我还没能找到办法来实现这一点。

答案1

好吧,这其实很简单:nginx 已经有一个指令,在决定是否缓存时忽略 Web 应用程序发送的上游 Cache-Control 和 Set-Cookie 标头,proxy_ignore_headers

proxy_ignore_headers Cache-Control Set-Cookie;

这还要求设置缓存生存期proxy_cache_valid, 例如:

proxy_cache_valid any 1d;

因此在此之后您可以(并且应该)只Cache-Control: private; ...从您的 Web 应用程序发送,并且 nginx 将缓存,但像 CloudFlare 这样的下游缓存则不会。

请注意,您proxy_cache_key需要某种方式来区分发送给使用相同 URL 的不同用户的响应,否则一个用户可能会看到另一个用户的数据。

欲了解更多信息,请务必阅读NGINX 缓存指南

答案2

我最终找到了一个解决方案,虽然感觉有点奇怪,但它确实有效。

它使用映射内的正则表达式将 Cache-Control 标头中的“public”替换为“private”。

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

...


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

相关内容