我的后端应用程序发送 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;