Spec-Zone.ru › Apache HTTP Server

Согласование содержимого

Apache HTTPD поддерживает согласование содержимого, описанное в спецификации HTTP/1.1. Он может выбирать наилучшее представление ресурса на основе предпочтений браузера по типу медиа, языкам, кодировке символов и способу кодирования. Также реализовано несколько функций для более интеллектуальной обработки запросов от браузеров, отправляющих неполную информацию для согласования.

Согласование содержимого обеспечивает модуль mod_negotiation, который по умолчанию включён в сборку.

О согласовании содержимого

Ресурс может быть доступен в нескольких различных представлениях. Например, он может быть доступен на разных языках или в разных типах медиа либо в различных сочетаниях того и другого. Один из способов выбрать наиболее подходящий вариант — предоставить пользователю страницу-указатель и позволить ему сделать выбор. Однако часто сервер может выбрать вариант автоматически. Это возможно, поскольку браузеры могут отправлять в каждом запросе сведения о предпочитаемых представлениях. Например, браузер может указать, что хотел бы получить информацию на французском языке, если это возможно, а в противном случае подойдёт английский. Браузеры указывают свои предпочтения с помощью заголовков запроса. Чтобы запросить только представления на французском языке, браузер отправил бы

Accept-Language: fr

Обратите внимание: это предпочтение будет учтено, только если есть выбор представлений, различающихся по языку.

В качестве примера более сложного запроса: этот браузер настроен на поддержку французского и английского языков с предпочтением французского, а также на поддержку различных типов медиа с предпочтением HTML перед обычным текстом и другими текстовыми типами и предпочтением GIF или JPEG перед другими типами медиа, но при этом допускает любой другой тип медиа в крайнем случае:

Accept-Language: fr; q=1.0, en; q=0.5
Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1

httpd поддерживает согласование содержимого «с управлением со стороны сервера», определённое в спецификации HTTP/1.1. Он полностью поддерживает заголовки запросов Accept, Accept-Language, Accept-Charset и Accept-Encoding. httpd также поддерживает «прозрачное» согласование содержимого — экспериментальный протокол согласования, определённый в RFC 2295 и RFC 2296. Поддержка «согласования возможностей», определённого в этих RFC, не предоставляется.

Ресурс — это концептуальная сущность, идентифицируемая URI (RFC 2396). HTTP-сервер, такой как Apache HTTP Server, предоставляет доступ к представлениям ресурса или ресурсов в своём пространстве имён; каждое представление имеет вид последовательности байтов с определённым типом медиа, кодировкой символов, способом кодирования и т. д. В любой момент времени с каждым ресурсом может быть связано ноль, одно или несколько представлений. Если доступно несколько представлений, ресурс называется согласуемым, а каждое из его представлений — вариантом. Способы, которыми различаются варианты согласуемого ресурса, называются измерениями согласования.

Согласование в httpd

Чтобы согласовать ресурс, серверу необходимо предоставить сведения о каждом из вариантов. Это можно сделать одним из двух способов:

  • Используя карту типов (т. е. файл *.var), в которой явно перечислены файлы с вариантами, или
  • Используя поиск «MultiViews», при котором сервер неявно сопоставляет шаблоны имён файлов и выбирает вариант из найденных результатов.

Использование файла карты типов

Карта типов — это документ, связанный с обработчиком с именем type-map (или с application/x-type-map типа MIME для обратной совместимости со старыми конфигурациями httpd). Обратите внимание: для использования этой функции в конфигурации должен быть задан обработчик, определяющий суффикс файла как type-map; удобнее всего сделать это с помощью

AddHandler type-map .var

в файле конфигурации сервера.

Файлы карт типов должны иметь то же имя, что и описываемый ими ресурс, с добавленным расширением .var. В приведённых ниже примерах ресурс называется foo, поэтому файл карты типов называется foo.var.

В этом файле должна быть запись для каждого доступного варианта; эти записи состоят из последовательных строк заголовков в формате HTTP. Записи разных вариантов отделяются пустыми строками. Пустые строки внутри записи недопустимы. Принято начинать файл карты с записи для сущности в целом (хотя это не обязательно, и такая запись, если она присутствует, будет проигнорирована). Пример файла карты приведён ниже.

URI в этом файле задаются относительно расположения файла карты типов. Обычно эти файлы находятся в том же каталоге, что и файл карты типов, но это не обязательно. Для любого файла на том же сервере, что и файл карты, можно указать абсолютный или относительный URI.

URI: foo

URI: foo.en.html
Content-type: text/html
Content-language: en

URI: foo.fr.de.html
Content-type: text/html;charset=iso-8859-2
Content-language: fr, de

Также обратите внимание, что файл карты типов имеет приоритет над расширением имени файла, даже если включён Multiviews. Если исходное качество вариантов различается, это можно указать параметром "qs" типа медиа, как в примере с этим изображением (доступным в формате JPEG, GIF или ASCII-графики):

URI: foo

URI: foo.jpeg
Content-type: image/jpeg; qs=0.8

URI: foo.gif
Content-type: image/gif; qs=0.5

URI: foo.txt
Content-type: text/plain; qs=0.01

Значения qs могут находиться в диапазоне от 0.000 до 1.000. Обратите внимание: вариант со значением qs, равным 0.000, никогда не будет выбран. Вариантам без значения параметра 'qs' присваивается коэффициент qs, равный 1.0. Параметр qs указывает относительное «качество» этого варианта по сравнению с другими доступными вариантами, независимо от возможностей клиента. Например, JPEG-файл обычно имеет более высокое исходное качество, чем файл ASCII, если он предназначен для представления фотографии. Однако если исходный ресурс — ASCII-графика, то представление в формате ASCII будет иметь более высокое исходное качество, чем представление JPEG. Поэтому значение qs зависит от конкретного варианта и определяется характером представляемого им ресурса.

Полный список распознаваемых заголовков приведён в документации карты типов mod_negotiation.

Multiviews

MultiViews — параметр, задаваемый для каталога. Это означает, что его можно установить директивой Options в секции <Directory>, <Location> или <Files> в файле httpd.conf либо (если правильно задан AllowOverride) в файлах .htaccess. Обратите внимание: Options All не включает MultiViews; её необходимо запросить по имени.

Действие MultiViews заключается в следующем: если сервер получает запрос для /some/dir/foo, если для /some/dir включён параметр MultiViews и /some/dir/foo не существует, сервер просматривает каталог в поисках файлов с именами foo.* и фактически формирует фиктивную карту типов, в которой перечислены все эти файлы, назначая им те же типы медиа и кодировки содержимого, которые были бы назначены, если бы клиент запросил один из них по имени. Затем сервер выбирает вариант, наилучшим образом соответствующий требованиям клиента.

MultiViews может также применяться при поиске файла, заданного директивой DirectoryIndex, если сервер пытается индексировать каталог. Если в файлах конфигурации указано

DirectoryIndex index

то сервер выберет между index.html и index.html3, если присутствуют оба файла. Если ни одного из них нет, но присутствует index.cgi, сервер запустит этот файл.

Если у одного из файлов, найденных при просмотре каталога, расширение не распознаётся директивой mod_mime как обозначение кодировки символов, типа содержимого, языка или кодирования, результат зависит от настройки директивы MultiViewsMatch. Эта директива определяет, могут ли обработчики, фильтры и другие типы расширений участвовать в согласовании MultiViews.

Методы согласования

Получив список вариантов данного ресурса — из файла карты типов или из имён файлов в каталоге, — httpd использует один из двух методов, чтобы определить, какой вариант (если таковой имеется) лучше всего вернуть. Чтобы пользоваться функциями согласования содержимого httpd, знать подробности процесса согласования необязательно. Тем не менее в оставшейся части этого документа описаны используемые методы для тех, кому это интересно.

Существует два метода согласования:

  1. Согласование с управлением со стороны сервера с использованием алгоритма httpd применяется в обычном случае. Алгоритм httpd подробнее описан ниже. При использовании этого алгоритма httpd иногда может «подправить» коэффициент качества для определённого измерения, чтобы получить лучший результат. Способы, которыми httpd может корректировать коэффициенты качества, подробнее описаны ниже.
  2. Прозрачное согласование содержимого используется, когда браузер явно запрашивает его с помощью механизма, определённого в RFC 2295. Этот метод согласования предоставляет браузеру полный контроль над выбором «наилучшего» варианта, поэтому результат зависит от конкретных алгоритмов браузера. В рамках процесса прозрачного согласования браузер может попросить httpd запустить «алгоритм удалённого выбора вариантов», определённый в RFC 2296.

Измерения согласования

Измерение Примечания
Тип медиа Браузер указывает предпочтения с помощью поля заголовка Accept. Для каждого элемента можно задать коэффициент качества. Описание варианта также может содержать коэффициент качества (параметр "qs").
Язык Браузер указывает предпочтения с помощью поля заголовка Accept-Language. Для каждого элемента можно задать коэффициент качества. С вариантами может быть связано ноль, одно или несколько значений языка.
Кодирование Браузер указывает предпочтение с помощью поля заголовка Accept-Encoding. Для каждого элемента можно задать коэффициент качества.
Кодировка символов Браузер указывает предпочтение с помощью поля заголовка Accept-Charset. Для каждого элемента можно задать коэффициент качества. Варианты могут указывать кодировку символов в качестве параметра типа медиа.

Алгоритм согласования httpd

Для выбора наилучшего варианта (если он есть), который будет возвращён браузеру, httpd может использовать следующий алгоритм. Дополнительная настройка этого алгоритма невозможна. Алгоритм работает следующим образом:

  1. Сначала для каждого измерения согласования проверьте соответствующее поле заголовка Accept* и назначьте каждому варианту значение качества. Если заголовок Accept* для какого-либо измерения указывает, что вариант неприемлем, исключите его. Если вариантов не осталось, перейдите к шагу 4.
  2. Выберите наилучший вариант методом исключения. Последовательно применяются следующие проверки. Варианты, не выбранные на каждой проверке, исключаются. После каждой проверки, если остался только один вариант, выберите его как наилучшее соответствие и перейдите к шагу 3. Если осталось больше одного варианта, перейдите к следующей проверке.
    1. Умножьте коэффициент качества из заголовка Accept на коэффициент исходного качества для типа медиа этого варианта и выберите варианты с наибольшим полученным значением.
    2. Выберите варианты с наибольшим коэффициентом качества языка.
    3. Выберите варианты с наилучшим соответствием языка, используя порядок языков в заголовке Accept-Language (если он присутствует) или порядок языков в директиве LanguagePriority (если она присутствует).
    4. Выберите варианты с наибольшим параметром медиа 'level' (он используется для указания версии типов медиа text/html).
    5. Выберите варианты с наилучшими параметрами медиа для кодировки символов, заданными в строке заголовка Accept-Charset. Кодировка ISO-8859-1 считается допустимой, если она явно не исключена. Предполагается, что варианты с типом медиа text/*, для которых явно не указана конкретная кодировка символов, имеют кодировку ISO-8859-1.
    6. Выберите варианты, связанные с параметрами медиа для кодировки символов, отличной от ISO-8859-1. Если таких вариантов нет, выберите все варианты.
    7. Выберите варианты с наилучшим кодированием. Если есть варианты с кодированием, допустимым для пользовательского агента, выберите только их. В противном случае, если есть как кодированные, так и некодированные варианты, выберите только некодированные. Если все варианты кодированы или все не кодированы, выберите их все.
    8. Выберите варианты с наименьшей длиной содержимого.
    9. Выберите первый из оставшихся вариантов. Это будет либо первый вариант в файле карты типов, либо, если варианты прочитаны из каталога, вариант с именем файла, которое идёт первым при сортировке в порядке кодов ASCII.
  3. Алгоритм выбрал наилучший вариант, поэтому верните его в качестве ответа. В заголовке HTTP-ответа Vary указываются измерения согласования (браузеры и кэши могут использовать эту информацию при кэшировании ресурса). Конец.
  4. Если выполнение дошло до этого шага, значит, ни один вариант не был выбран (поскольку ни один из них не подходит браузеру). Верните статус 406 (означающий «Нет допустимого представления») с телом ответа в виде HTML-документа, перечисляющего доступные варианты. Также установите заголовок HTTP Vary, указывающий измерения различий.

Корректировка значений качества

Иногда httpd изменяет значения качества по сравнению с теми, которые следовало бы получить при строгой интерпретации описанного выше алгоритма согласования httpd. Это позволяет алгоритму выдавать лучший результат для браузеров, которые отправляют неполную или неточную информацию. Некоторые из наиболее популярных браузеров отправляют информацию в заголовке Accept, которая во многих случаях в противном случае приводила бы к выбору неправильного варианта. Если браузер отправляет полную и точную информацию, эти корректировки не применяются.

Типы медиа и подстановочные знаки

Заголовок запроса Accept: указывает предпочтения для типов медиа. Он также может содержать типы медиа с «подстановочными знаками», например "image/*" или "*/*", где * соответствует любой строке. Поэтому запрос, содержащий:

Accept: image/*, */*

означал бы, что допустим любой тип, начинающийся с "image/", а также любой другой тип. Некоторые браузеры регулярно отправляют подстановочные знаки в дополнение к типам, поддержку которых они явно указывают. Например:

Accept: text/html, text/plain, image/gif, image/jpeg, */*

Это означает, что явно перечисленные типы предпочтительны, но подойдёт и другое доступное представление. Если использовать явные значения качества, то браузер на самом деле хочет получить примерно следующее:

Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01

Для явно указанных типов коэффициент качества не задан, поэтому по умолчанию их предпочтение равно 1.0 (наивысшее). Подстановочному знаку */* присваивается низкое предпочтение 0.01, поэтому другие типы будут возвращены только в том случае, если ни один вариант не соответствует явно указанному типу.

Если заголовок Accept: вообще не содержит коэффициентов q, httpd устанавливает значение q для "*/*", если он присутствует, равным 0.01, чтобы имитировать желаемое поведение. Также он устанавливает значение q для подстановочных знаков формата "type/*" равным 0.02 (поэтому они предпочтительнее совпадений с "*/*"). Если какой-либо тип медиа в заголовке Accept: содержит коэффициент q, эти специальные значения не применяются, и запросы браузеров, которые изначально отправляют явную информацию, обрабатываются ожидаемым образом.

Исключения при согласовании языков

Начиная с httpd 2.0, в алгоритм согласования добавлены исключения, позволяющие корректно обработать ситуацию, когда согласование языка не находит совпадений.

Если клиент запрашивает страницу на вашем сервере, но сервер не может найти ни одной страницы, соответствующей заголовку Accept-language, отправленному браузером, сервер вернёт клиенту ответ "No Acceptable Variant" или "Multiple Choices". Чтобы избежать этих сообщений об ошибках, можно настроить httpd так, чтобы в таких случаях он игнорировал Accept-language и предоставлял документ, который явно не соответствует запросу клиента. Директива ForceLanguagePriority позволяет переопределить одно или оба этих сообщения об ошибках и использовать вместо них решение сервера в форме директивы LanguagePriority.

Если найти другое совпадение не удаётся, сервер также попытается подобрать вариант с совпадающим подмножеством языковых тегов. Например, если клиент запрашивает документы на языке en-GB (британский английский), стандарт HTTP/1.1 обычно не позволяет серверу сопоставить этот запрос с документом, отмеченным просто как en. (Обратите внимание: включать en-GB, но не en в заголовок Accept-Language почти наверняка является ошибкой конфигурации, поскольку крайне маловероятно, что читатель понимает британский английский, но не понимает английский в целом. К сожалению, у многих современных клиентов настройки по умолчанию именно таковы.) Однако, если совпадений по другим языкам нет и сервер собирается вернуть ошибку "No Acceptable Variants" или перейти к LanguagePriority, он проигнорирует спецификацию подмножества и сопоставит en-GB с документами en. Неявно httpd добавит родительский язык в список допустимых языков клиента с очень низким значением качества. Но учтите: если клиент запрашивает "en-GB; q=0.9, fr; q=0.8", а на сервере есть документы с обозначениями "en" и "fr", будет возвращён документ "fr". Это необходимо для соблюдения спецификации HTTP/1.1 и эффективной работы с правильно настроенными клиентами.

Для поддержки расширенных методов определения предпочтительного языка пользователя (например, с помощью файлов cookie или специальных путей URL) начиная с httpd 2.0.47 mod_negotiation распознаёт переменную окружения prefer-language. Если она существует и содержит подходящий языковой тег, mod_negotiation попытается выбрать соответствующий вариант. Если такого варианта нет, применяется обычный процесс согласования.

Пример

SetEnvIf Cookie "language=(.+)" prefer-language=$1
Header append Vary cookie

Расширения прозрачного согласования содержимого

httpd расширяет протокол прозрачного согласования содержимого (RFC 2295) следующим образом. В списках вариантов используется новый элемент {encoding ..} для обозначения вариантов, доступных только с определённым кодированием содержимого. Реализация алгоритма RVSA/1.0 (RFC 2296) расширена для распознавания кодированных вариантов в списке и использования их в качестве кандидатов, если их кодировки допустимы согласно заголовку запроса Accept-Encoding. Реализация RVSA/1.0 не округляет вычисленные коэффициенты качества до 5 знаков после запятой перед выбором наилучшего варианта.

Примечание о гиперссылках и соглашениях об именовании

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

Обычно файл имеет расширение типа MIME (например, html), возможно, расширение кодирования (например, gz), а также расширение языка (например, en), если у этого файла есть варианты на разных языках.

Примеры:

  • foo.en.html
  • foo.html.en
  • foo.en.html.gz

Ниже приведено ещё несколько примеров имён файлов, а также допустимых и недопустимых гиперссылок:

Имя файла Допустимая гиперссылка Недопустимая гиперссылка
foo.html.en foo
foo.html
-
foo.en.html foo foo.html
foo.html.en.gz foo
foo.html
foo.gz
foo.html.gz
foo.en.html.gz foo foo.html
foo.html.gz
foo.gz
foo.gz.html.en foo
foo.gz
foo.gz.html
foo.html
foo.html.gz.en foo
foo.html
foo.html.gz
foo.gz

Из приведённой выше таблицы видно, что в гиперссылке всегда можно использовать имя без расширений (например, foo). Это позволяет скрыть фактический тип документа или файла и позднее изменить его, например, с html на shtml или cgi, не меняя ссылки в гиперссылках.

Если вы хотите и дальше указывать тип MIME в гиперссылках (например foo.html), расширение языка (включая расширение кодирования, если оно есть) должно находиться справа от расширения типа MIME (например, foo.html.en).

Примечание о кэшировании

Когда кэш сохраняет представление, он связывает его с URL запроса. При следующем запросе этого URL кэш может использовать сохранённое представление. Однако если ресурс на сервере является согласуемым, в результате может быть кэширован только первый запрошенный вариант, а при последующих обращениях к кэшу может возвращаться неверный ответ. Чтобы этого избежать, httpd обычно помечает все ответы, возвращённые после согласования содержимого, как не подлежащие кэшированию клиентами HTTP/1.0. httpd также поддерживает функции протокола HTTP/1.1, позволяющие кэшировать согласованные ответы.

Для запросов от клиентов, совместимых с HTTP/1.0 (браузеров или кэшей), директиву CacheNegotiatedDocs можно использовать, чтобы разрешить кэширование ответов, полученных в результате согласования. Эту директиву можно задать в конфигурации сервера или виртуального хоста; аргументы она не принимает. На запросы клиентов HTTP/1.1 она не влияет.

Для клиентов HTTP/1.1 httpd отправляет заголовок HTTP-ответа Vary, указывающий измерения согласования для ответа. Кэши могут использовать эту информацию, чтобы определить, можно ли обслужить последующий запрос из локальной копии. Чтобы побудить кэш использовать локальную копию независимо от измерений согласования, задайте переменную окружения force-no-vary.

© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/content-negotiation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API