Назад | Перейти на главную страницу

Насколько безопасно использовать proxy_ignore_headers Vary?

Я использую сервер Nginx, который действует как кеш / обратный прокси для моего исходного сервера Apache.

я изо всех сил пытался отладить высокая скорость кеширования MISS когда я обнаружил, что это потому, что заголовок ответа Vary: Accept-Encoding, разные клиенты www с разными Accept-Encoding не получали HIT, даже если точно такой же URL-адрес был ранее запрошен другим клиентом.

Это можно исправить, добавив конфигурацию nginx:

proxy_ignore_headers Vary;

После этого я получаю HIT кешировать ответы.

а) Отключает ли это различные варианты кешированных страниц? просто между моим кеш-сервером и исходным сервером? (например, безопасно использовать)

б) Или он кэширует одну версию (файл с gzip или без gzip) для всех конечных клиентов, независимо от возможностей клиентского кодирования / декодирования? Я думаю, это может привести к тому, что клиент, не поддерживающий gzip, получит файл gziped?

Даже если кеш улучшен / исправлен указанной выше директивой, конечный клиент все равно получает Vary: Accept-Encoding, его можно скрыть с помощью proxy_hide_header Varyа я должен?

Я провел небольшое расследование по этому поводу. Я думаю, что нашел ценную информацию в обсуждении GitHub в Yichun Zhang (автор форка OpenResty nginx) Ответить:

Предлагаю следующие варианты:

  1. Кэшируйте как сжатые, так и несжатые ответы и добавьте (в каноническом) значении Accept-Encoding в свой ключ кеша. Таким образом, клиенты, которые не ожидают ответов gzip'd, приводят к пропуску кеша (и запускают кеширование несжатой версии).
  2. Кэшируйте сжатые ответы и используйте стандартный модуль ngx_gunzip для распаковки тела ответа для тех клиентов, которые не принимают кодировку gzip :. Видеть http://nginx.org/en/docs/http/ngx_http_gunzip_module.html Но вам нужно быть осторожным с порядком выходного фильтра nginx (между фильтром ngx_srcache и фильтром ngx_gunzip).
  3. Кэшируйте только несжатый контент и полагайтесь на модуль ngx_gzip для сжатия данных для тех клиентов, которые ожидают gzip. Установить proxy_set_header Accept-Encoding ''; например, если прокси-модуль используется в качестве обработчика содержимого.

Похоже, это небезопасно, и вам следует кэшировать оба ответа (сжатый и несжатый).

Но что произойдет, если вы получите несколько запросов со следующими Accept-Encoding заголовки:

  • Accept-Encoding: gzip
  • Accept-Encoding: gzip, br
  • Accept-Encoding: gzip;q=0.8, br;q=0.9
  • Accept-Encoding: gzip, deflate, br

Значит ли это, что каждый ответ будет кешироваться отдельно? Я пока не знаю, это требует более обширного тестирования, которое я уже проводил. Что я нашел на данный момент:

  • nginx не отвечает на Accept-Encoding: deflate со спущенным ответом (который лишь немного отличается от сжатого с помощью gzip).
  • nginx не учитывает весовую часть заголовка qvalue. Он ответит сжатым ответом на запрос с Accept-Encoding: identity;q=0.8, gzip;q=0.5 заголовок. Если у тебя есть ngx_brotly установленный модуль, nginx всегда будет отвечать, если ваш Accept-Encoding заголовок запроса содержит br метод сжатия независимо от того, какие веса указаны для методов сжатия.

Ичунь Чжан упоминает о добавлении (канонического) значения Accept-Encoding в ваш ключ кеша. Это может быть что-то вроде

map $http_accept_encoding $encoding_key {
    ~[\s:,]br(?:[\s,;]|$)       2; # brotli
    ~[\s:,]gzip(?:[\s,;]|$)     1; # gzip
    default                     0; # uncompressed
}

Если вы не используете ngx_brotly модуль, все можно упростить:

if ($http_accept_encoding ~ "[\s:,]gzip(?:[\s,;]|$)") {
    set $encoding_key 1;
}

После этого добавление $encoding_key переменная для proxy_cache_key Expression может помочь, но, как я уже сказал, это требует более тщательного тестирования.