Джанго отсутствует Vary: заголовок Cookie для кэшированных представлений
У меня довольно сложное веб-приложение, основанное на Django 1.11. Некоторое время назад пользователи начали сообщать, что они получают "чужие взгляды" - memcached предоставил им html, кэшированный декоратором @cache_page(xx)
без различия между сессиями в течение льготного периода кеширования.
После дальнейшего расследования я обнаружил, что в некоторых случаях Vary: Cookie
заголовок отсутствовал и неправильный сеанс Что странно, это показывалось только при запросе серверной части с помощью curl (у которой нет сеанса, пользователь и т. Д. -> серверная служба была зарегистрирована в кэшированном представлении).
К сожалению, эту проблему очень трудно воспроизвести, иногда это происходит, иногда нет. Я даже создаю простое приложение Django с нуля, чтобы посмотреть, смогу ли я выяснить, в чем причина. Что наблюдалось, так это то, что проблема не возникает, когда @cache_page
удален или login_required
добавлен.
В итоге я удалил все декораторы @cache_page из представлений, и с тех пор проблема не наблюдалась на производстве, но это обходной путь, и я хотел бы знать, в чем причина.
Если у кого-нибудь есть подсказка, в чем может быть причина, это будет с благодарностью!
1 ответ
Вы, вероятно, сталкиваетесь с этой открытой ошибкой:
Поскольку декораторы представления запускаются на исходящем ответе в первую очередь, до промежуточного программного обеспечения ответа,
cache_page
decorator кэширует ответ до того, как какое-либо из упомянутых промежуточных программ отклика сможет добавить свои заголовки 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