Какова функция HTTP-заголовка «Vary: Accept»?

93

Я использую PHP для создания динамических веб-страниц. Как указано в следующем руководстве (см. Ссылку ниже), тип MIME для документов XHTML должен быть «application / xhtml + xml», если $ _SERVER ['HTTP_ACCEPT'] позволяет это. Поскольку вы можете обслуживать одну и ту же страницу с двумя разными MIME («application / xhtml + xml» и «text / html»), вам следует установить HTTP-заголовок «Vary» на «Accept». В этом поможет кеш на прокси.

Ссылка: http://keystonewebsites.com/articles/mime_type.php

Теперь я не уверен в значении: header ('Vary: Accept'); Я не совсем уверен, что именно будет делать «Vary: Accept» ...

Единственное объяснение, которое я нашел:

После заголовка Content-Type отправляется заголовок Vary (если я правильно понимаю), чтобы сообщить промежуточным кешам, таким как прокси-серверы, что тип содержимого документа зависит от возможностей клиента, запрашивающего документ. http://www.456bereastreet.com/archive/200408/content_negotiation/

Кто угодно может дать мне «настоящее» объяснение этого заголовка ( с таким значением ). Я думаю, что понимаю такие вещи, как: Vary: Accept-Encoding, где кеш на прокси-серверах может быть основан на кодировке обслуживаемой страницы, но я не понимаю: Vary: Accept

AlexV
источник
1
Откровенно говоря - не беспокойтесь. Не говоря уже о недостатках реализации на этом сайте, единственный раз, когда вы собираетесь получить выгоду от обслуживания с типом содержимого XML, - это когда вы делаете то, что невозможно сделать в text / html - и если все, что вы делаете отключает Doctype и xmlns, то вы не собираетесь делать эти вещи. Придерживайтесь text / html. В этом отношении вы можете придерживаться HTML 4.01.
Квентин,
Да, я понимаю это и думаю, что «проблемы», подобные этой, слишком часто возникают в веб-разработке. Благодаря "следует" в спецификациях / RFC!
AlexV
2
Вам, вероятно, следует прочитать это: blogs.msdn.com/ieinternals/archive/2009/06/17/…, прежде чем рассматривать возможность использования VARY.
EricLaw 05
1
В этом видео есть хорошее объяснение Vary:заголовка.
Каннан Мохан

Ответы:

94
  • cache-controlЗаголовок является основным механизмом для сервера HTTP , чтобы сказать кэширующий прокси - сервера «свежесть» в ответ. (т.е. как / если долго хранить ответ в кеше)

  • В некоторых ситуациях cache-controlдиректив недостаточно. Здесь заархивировано обсуждение рабочей группы HTTP , описывающее страницу, которая изменяется только в зависимости от языка. Это не правильный вариант использования для изменяться заголовок, но контекст является ценным для нашей дискуссии. (Хотя я считаю, что заголовок Vary решит проблему в этом случае, есть способ лучше.) На этой странице:

Vary строго для тех случаев, когда прокси-серверу безнадежно или слишком сложно воспроизвести то, что будет делать сервер.

Надуманный пример:

У вашего HTTP-сервера большая целевая страница. У вас есть две немного разные страницы с одним и тем же URL, в зависимости от того, был ли пользователь на них раньше. Вы различаете запросы и «количество посещений» пользователя на основе файлов cookie. Но - поскольку целевая страница вашего сервера настолько велика, вам нужно, чтобы промежуточные прокси кэшировали ответ, если это возможно.

Заголовки URL, Last-Modified и Cache-Control недостаточны для того, чтобы дать эту информацию кеширующему прокси, но если вы добавите Vary: Cookie, механизм кеширования добавит заголовок Cookie в свои решения кеширования.

Наконец, для небольшого трафика динамические веб-сайты - я всегда находил простое Cache-Control: no-cache, no-storeи Pragma: no-cacheдостаточное.

Изменить - чтобы более точно ответить на ваш вопрос: заголовок HTTP-запроса «Принять» определяет типы содержимого, которые может обрабатывать клиент. Если у вас есть две копии одного и того же контента по одному и тому же URL-адресу, различающиеся только Content-Type, тогда использование Vary: Acceptможет быть подходящим.

Обновление 11 сентября 12:

Я включаю пару ссылок, которые появились в комментариях с момента первоначальной публикации этого комментария. Оба они являются отличными ресурсами для реальных примеров (и проблем) с Vary: Accept; Если вы читаете этот ответ, вам также необходимо прочитать эти ссылки.

Первый, от выдающегося EricLaw, о поведении Internet Explorer с заголовком Vary и некоторых проблемах, которые он ставит перед разработчиками: Vary Header предотвращает кеширование в IE . Короче говоря, IE (до IE9) не кэширует какой-либо контент, который использует заголовок Vary, потому что кеш запроса не включает заголовки HTTP-запроса. Эрик Лоу (Эрик Лоуренс в реальном мире) - менеджер программы в команде IE.

Второй - от Эрана Медана, и это постоянное обсуждение неожиданного поведения, связанного с Vary, в Chrome: поддержка некорректно обрабатывает заголовок Vary . Это связано с поведением IE, за исключением того, что разработчики Chrome использовали другой подход - хотя, похоже, это не было осознанным выбором.

JJ
источник
3
Остерегайтесь этого в сочетании с кнопкой возврата в браузере в Chrome, это своего рода война с этой ошибкой (которая теперь по какой-то причине не исправляется
Эран Medan
6
@EranMedan С тех пор ошибка Chrome была исправлена.
59

Vary: Acceptпросто говорит, что ответ был создан на основе Acceptзаголовка в запросе. Запрос с другим Acceptзаголовком может получить другой ответ.

(Вы можете видеть, что связанный код PHP смотрит $HTTP_ACCEPT. Это значение Acceptзаголовка запроса.)

Для HTTP-кешей это означает, что ответ необходимо кэшировать с особой осторожностью. Это будет действительное совпадение только для последующих запросов с точно таким же Acceptзаголовком .

Теперь это имеет значение только в том случае, если страница вообще кэшируется. По умолчанию страницы PHP нет. Страница PHP может пометить вывод как кэшируемый, отправив определенные заголовки ( Expiresнапример). Но нужно ли это делать и как - другой вопрос.

Джейсон Орендорф
источник
это «может получить» или «должно получить»?
Pacerier
6
@Pacerier "может получить" правильно. Vary: Acceptне означает, что каждое возможное отдельное Acceptзначение заголовка дает разный и уникальный ответ. Это только означает, что другой Acceptзаголовок может дать другой ответ.
Джейсон Орендорф
2

На самом деле в ближайшее время появится значительное количество новых функций (и уже в Chrome), которые сделают Varyзаголовок чрезвычайно полезным. Например, рассмотрим подсказку клиента . Например, при использовании в сочетании с изображениями клиентские подсказки позволяют серверу оптимизировать ресурсы, такие как изображения, в зависимости от:

  • Ширина изображения
  • Ширина области просмотра
  • Тип кодировки, поддерживаемый браузером (например, WebP)
  • Downlink (в основном скорость сети)

Таким образом, сервер, который поддерживает эти функции, установит Varyзаголовок, чтобы указать это.

Chrome рекламирует поддержку WebP, устанавливая «image / webp» как часть Varyзаголовка для каждого запроса. Таким образом, сервер может переписать изображение как WebP, если браузер поддерживает его, поэтому прокси-сервер должен будет проверить заголовок, чтобы не кэшировать изображение WebP, а затем передать его в браузер, который не поддерживает WebP. Очевидно, если ваш сервер этого не делает, это не имеет значения. Итак, поскольку ответ сервера зависит от Acceptзаголовка запроса, ответ должен включать это, чтобы не путать прокси:

Vary: Accept

Другой пример - ширина изображения. В мобильном браузере Widthзаголовок может быть довольно маленьким для отзывчивого изображения по сравнению с тем, каким он был бы при просмотре в браузере настольного компьютера. Так что в этом случаеWidth он будет добавлен в Varyзаголовок, чтобы прокси не кэшировал небольшую мобильную версию и не обслуживал ее в настольных браузерах или наоборот. В этом случае заголовок может включать:

Vary: Accept, Width

Или в случае, если сервер поддерживает все спецификации подсказок клиента, заголовок будет примерно таким:

Vary: Accept, DPR, Width, Save-Data, Downlink
Брэд Бергер
источник