[英]Django missing Vary:Cookie header for cached views
我有一個基於Django 1.11的非常復雜的webapp。 前段時間用戶開始報告他們正在獲取“其他人的觀點” - memcached為他們提供了由裝飾者@cache_page(xx)
緩存的html,而沒有區分緩存寬限期內的會話。
經過進一步調查,我發現在某些情況下, Vary: Cookie
標頭丟失,錯誤的“會話”被提供。 奇怪的是,它僅在使用curl查詢后端時顯示(沒有會話,用戶等 - >后端服務登錄緩存視圖)。
不幸的是,這個問題很難重現,有時它會發生,有時則不會。 我甚至從頭開始構建一個簡單的Django應用程序,看看我是否可以檢查是什么原因。 觀察到的是,刪除@cache_page
或添加login_required
時不會發生此問題。
我最終從視圖中刪除了所有@cache_page裝飾器,並且在生產中沒有觀察到問題,但這是一種解決方法,我想知道原因是什么。
如果有人有任何暗示可能是什么原因,將不勝感激!
你可能遇到這個開放的bug :
由於視圖裝飾器首先在傳出響應上運行,在響應中間件之前,
cache_page
裝飾器在任何提到的響應中間件有機會添加其Vary頭之前緩存響應。 這意味着兩件事:1)使用的緩存密鑰不包括響應應該變化的標頭,Django可能稍后將響應提供給真正不應該獲得它的用戶,以及2)當緩存的響應稍后時服務於用戶,它仍然不包括它應該具有的Vary
頭,因此也可能被上游HTTP緩存錯誤地緩存。
換句話說,在緩存響應時, SessionMiddleware
還沒有機會設置Vary: Cookie
標頭,因此所有會話將共享相同的緩存鍵。
您可以通過顯式指定Vary
標頭來解決此問題。 例如:
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.