简体   繁体   English

Django缺少Vary:缓存视图的Cookie标头

[英]Django missing Vary:Cookie header for cached views

I've got a pretty complex webapp based on Django 1.11. 我有一个基于Django 1.11的非常复杂的webapp。 Some time ago users started reporting that they are getting 'someone else's views' - memcached provided them with html cached by decorator @cache_page(xx) without distinguishing between sessions within the cache grace period. 前段时间用户开始报告他们正在获取“其他人的观点” - memcached为他们提供了由装饰者@cache_page(xx)缓存的html,而没有区分缓存宽限期内的会话。

Upon further investigation, I discovered that in some cases Vary: Cookie header was missing and wrong 'session' was served. 经过进一步调查,我发现在某些情况下, Vary: Cookie标头丢失,错误的“会话”被提供。 What's strange, it only showed when querying backend with curl (which has no session, user etc -> backend served logged in cached view). 奇怪的是,它仅在使用curl查询后端时显示(没有会话,用户等 - >后端服务登录缓存视图)。

Unfortunately, this issue is really hard to reproduce, sometimes it occures, sometimes it doesn't. 不幸的是,这个问题很难重现,有时它会发生,有时则不会。 I even build a simple Django app from scratch to see if I could check what is the cause. 我甚至从头开始构建一个简单的Django应用程序,看看我是否可以检查是什么原因。 What was observed, is that the issue does not occur when @cache_page is removed or login_required is added . 观察到的是,删除@cache_page或添加login_required时不会发生此问题。

I ended up removing all @cache_page decorators from views and the issue was not observed on production since but it's a workaround and I would like to know what is the cause. 我最终从视图中删除了所有@cache_page装饰器,并且在生产中没有观察到问题,但这是一种解决方法,我想知道原因是什么。

If anyone has any hint what could be the cause, it would be greatly appreciated! 如果有人有任何暗示可能是什么原因,将不胜感激!

You're probably running into this open bug : 你可能遇到这个开放的bug

Since view decorators run on the outgoing response first, before response middleware, the cache_page decorator caches the response before any of the mentioned response middlewares have a chance to add their Vary headers. 由于视图装饰器首先在传出响应上运行,在响应中间件之前, cache_page装饰器在任何提到的响应中间件有机会添加其Vary头之前缓存响应。 This means two things: 1) the cache key used won't include the headers the response ought to vary on, and Django may later serve that response to users who really shouldn't get it, and 2) when that cached response is later served to a user, it still won't include the Vary header that it should have, and thus may also be cached wrongly by an upstream HTTP cache. 这意味着两件事:1)使用的缓存密钥不包括响应应该变化的标头,Django可能稍后将响应提供给真正不应该获得它的用户,以及2)当缓存的响应稍后时服务于用户,它仍然不包括它应该具有的Vary头,因此也可能被上游HTTP缓存错误地缓存。

In other words, at the time that the response is cached the SessionMiddleware hasn't yet had a chance to set the Vary: Cookie header, so all sessions will share the same cache key. 换句话说,在缓存响应时, SessionMiddleware还没有机会设置Vary: Cookie标头,因此所有会话将共享相同的缓存键。

You can probably work around this by specifying the Vary header explicitly. 您可以通过显式指定Vary标头来解决此问题。 For example: 例如:

from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie

@cache_page()
@vary_on_cookie()
def my_view():
    pass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM