Джанго отсутствует 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
Другие вопросы по тегам