Вопрос или проблема
Я пытаюсь активировать сжатие gzip и установил опцию gzip_vary on; чтобы включить заголовок Vary: Accept-Encoding.
Проблема в том, что моё приложение уже устанавливает заголовок Vary:. Так что теперь в ответе есть два заголовка Vary:, один от моего приложения и один от nginx.
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 17 Dec 2016 13:28:38 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Sat, 17 Dec 2016 13:28:38 GMT
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Vary: User-Agent
Content-Encoding: gzip
Но я предположу, что это должно быть скорее так:
Vary: Accept-Encoding, User-Agent
Как я могу этого добиться?
RFC2616 утверждает, что дубликаты заголовков допустимы и должны рассматриваться так же, как единый заголовок с перечисленными значениями через запятую:
Множественные поля заголовков сообщения с одинаковым именем поля могут присутствовать в сообщении, если и только если всё значение поля для этого заголовка определено как список, разделённый запятыми [т.е. #(значения)]. Должно быть возможно объединить множественные заголовки в одну пару “имя поля: значение поля”, не изменяя семантику сообщения, добавляя каждое последующее значение поля к первому, каждое разделённое запятой. Порядок, в котором заголовки с одинаковым именем поля получены, поэтому имеет значение для интерпретации объединённого значения поля, и, следовательно, прокси не должен изменять порядок этих значений поля при пересылке сообщения.
Таким образом, вам не нужно ничего делать, чтобы добиться правильного поведения.
RFC 2616 был заменён RFC 9110. Раздел 5.2 RFC 9110 гласит:
Когда имя поля присутствует только один раз в разделе, объединённое “значение поля” для этого поля состоит из соответствующего значения строки поля. Когда имя поля повторяется в рамках раздела, его объединённое значение поля состоит из списка соответствующих значений строк полей в этом разделе, соединённых в порядке, с каждым значением строки поля, разделённым запятой.
Например, этот раздел:
Example-Field: Foo, Bar
Example-Field: Baz
содержит две строки полей, обе с именем поля “Example-Field”. Первая строка поля имеет значение строки поля “Foo, Bar”, в то время как значение второй строки поля “Baz”. Значение поля для “Example-Field” – это список “Foo, Bar, Baz”.
С учётом этого раздела, http заголовок “vary” позволяет серверу объединять несколько значений строк полей в виде списка, разделённого запятыми, так что согласно этой логике, что-то вроде
vary: accept-encoding
vary: user-agent
аналогично
vary: accept-encoding, user-agent
Вы можете использовать gzip таким образом.
gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js image/gif image/jpeg application/atom+xml application/rss+xml text/x-component image/png image/tiff image/vnd.wap.wbmp image/x-icon image/x-jng image/x-ms-bmp image/svg+xml image/webp application/font-woff application/msword application/pdf;
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
Проверьте эту ссылку для получения дополнительной информации Сжать трафик между uwsgi-nginx и nginx балансировщиком нагрузки
Ответ или решение
Для активации сжатия Gzip в Nginx и правильной работы заголовка Vary
, вам нужно понимать, как Nginx управляет заголовками и как можно их эффективно комбинировать, чтобы избежать дублирования.
Проблема дублирования заголовков Vary
Как вы уже заметили, ваш сервер Nginx добавляет заголовок Vary: Accept-Encoding
, а ваше приложение добавляет свой собственный заголовок Vary: User-Agent
. Это приводит к тому, что в ответе появляются два отдельных заголовка Vary
, что может создать потенциальную путаницу.
Согласно RFC 9110, заголовки с одинаковыми именами могут быть объединены в один заголовок с витком значений, разделенных запятыми. Например:
Vary: Accept-Encoding, User-Agent
Как изменить поведение Nginx
Чтобы настроить Nginx таким образом, чтобы он объединял свои заголовки с заголовками, установленными приложением, следует воспользоваться директивой add_header
. Эта директива позволяет добавлять заголовки к ответам и может быть настроена так, чтобы включать существующие заголовки. Вы можете использовать следующий подход:
-
Настройте Nginx для объединения заголовков. Для этого вам нужно будет использовать директиву
add_header
в вашем конфигурационном файле Nginx, что позволит добавить нужные значения:http { gzip on; gzip_http_version 1.1; gzip_vary on; gzip_comp_level 6; gzip_proxied any; gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js image/gif image/jpeg application/atom+xml application/rss+xml text/x-component image/png image/tiff image/vnd.wap.wbmp image/x-icon image/x-jng image/x-ms-bmp image/svg+xml image/webp application/font-woff application/msword application/pdf; gzip_buffers 16 8k; gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # Объединение заголовков Vary add_header Vary "Accept-Encoding, $http_vary" always; }
В этом примере
$http_vary
будет содержать существующее значение заголовкаVary
, установленного вашим приложением. Однако обратите внимание на то, что вам может потребоваться добавить логику для удаления дубликатов и завершения заголовков, чтобы избежать повторяющихся значений. -
Перезапустите Nginx после изменения конфигурации:
sudo systemctl restart nginx
Завершение работы
Теперь, когда вы настроили вашу конфигурацию, каждый ответ от Nginx будет содержать один заголовок Vary
, который будет объединять значения из Nginx и вашего приложения. Таким образом, вы избежите лишних заголовков и улучшите соответствие стандартам HTTP.
Следуя данным рекомендациям, вы сможете эффективно управлять заголовками Vary
в вашем проекте и поддерживать его в соответствии с последними стандартами. Это не только улучшит производительность вашего веб-сервера, но и обеспечит лучшее взаимодействие с клиентами, что критически важно для оптимизации веб-приложений.