Как это работает
В этом документе описан алгоритм, по которому Apache-RUS определяет в какой
кодировке документ должен быть отдан клиенту. В каком-то смысле это повторение
описания директив конфигурации, но порядок
изложения
отвечает именно поведению сервера, при этом подробное описание директив опущено.
В документе описана текущая версия (PL20). Конфигурация (в т.ч. и
названия директив) старых версий (PL16 и более старых) отличается и описана
в отдельном документе. В тех местах, где поведение
новых и старых версий сервера отличается принциписально сделаны специальные
оговорки.
В дальнейшем тексте термины charset и кодировка используются практически
как синонимы.
Предварительные замечания
Основное назначение модуля, отвечающего за перекодировки, - произвести
корректное
преобразование из "charset на диске" (кодировка хранения)
в "charset у клиента" (кодировка передачи) при передаче документа
клиенту и произвести обратное преобразование при приеме информации от
клиента (submit формы и т.п.). Все возможные способы таких преобразований
должно быть описано в конфигурации
сервера директивами CharsetDecl
(объявление серверу о существовании кодовой таблицы) и
CharsetRecodeTable
(описание преобразования из одной кодировки в другую). Все имеющиеся
кодировки и преобразования могут быть описаны только в конфигурации
сервера/виртуального сервера. Описание директив CharsetDecl и
CharsetRecodeTable в .htaccess/<Directory> не допускается по
очевидной причине - такое описание требует, чтобы сервер переинициализировал
таблицы перекодировки при каждом обращении к такой директории, что ведет
к очень большому количеству лишних действий. Все прочие директивы
Charset... могут быть указаны где угодно.
Кодировка хранения (т.е. та, в которой файлы хранятся на диске) должна быть
указана (возможно, отдельно для каждой директории) директивой
CharsetSourceEnc
(описывает все файлы в директории) или директивой
CharsetByExtension. Директива
CharsetByExtension имеет больший приоритет.
Определение кодировки клиента по Accept-Charset:/Accept
В случае, если в HTTP-заголовках присутствует заголовок
Accept-Charset: SomeCharset или Accept: text/x-cyrillic-SomeCharset, и как
минимум один из запрошенных charset известен
серверу (т.е. описан в директивах
CharsetDecl
или CharsetAlias), то сервер выдает
документ в соответствии с запрошенным charset. Если серверу известны несколько из
запрошенных charset, то будет выбран имеющий наибольший приоритет. Если несколько
charset в запросе имеют одинаковый наибольший приоритет, то будет выбран тот из них,
который раньше описан в директиве
CharsetPriority.
Если при этом отсутствует и директива CharsetPriority, то результат выбора
из этих charset с наибольшим приоритетом не определен.
Если в заголовке Accept-Charset (Accept) указаны только charset неизвестные
серверу и не указан wildcard (*), то поведение сервера зависит от флага
CharsetErrReject. Если этот флаг
включен (On), то клиенту вернут сообщение об ошибке. Если выключен - сервер
попробует определить charset клиента по прочим параметрам.
Определение кодировки клиента по прочим параметрам
Если заголовки AcceptCharset/Accept в запросе отсутствуют, либо по ним не удалось
произвести выбор кодировки, то сервер попробует определить кодировку пользователя
по трем параметрам:
- По номеру порта (работает начиная с версии PL20.2). В случае, когда TCP-port
к которому идет обращение совпадает с одним из описанных директивой
CharsetByPort, то будет
выбрана эта кодировка.
- По Hostname сервера. В случае, если hostname сервера (виртуального сервера)
начинается с названия charset (CharsetDecl) или с алиаса Charset
(CharsetAlias), то в качестве клиентской кодировки будет выбрана эта
кодировка.
- По префиксу URL. Если URL начинается с /charset-name/path/to/file.html или
с /~user/charset-name/path/to/file.html, то будет выбрана эта кодировка.
- По программному обеспечению пользователя (HTTP-заголовку User-Agent). Если
в заголовке User-Agent есть подстрока, описанная в директиве
CharsetAgent, то будет выбрана
соответствующая кодировка. Если совпадающих подстрок несколько, то сработает самая
длинная. Если совпадающих подстрок несколько и они имеют одинаковую длину, то
выбор из них не определен.
Порядок срабатывания этих способов определяется директивой
CharsetSelectionRules
(В версиях до PL16 можно было менять местами только порядок срабатывания
Directory Prefix/UserAgent и выключать (по отдельности) Hostname prefix и
Directory Prefix).
Если у сервера ничего не получилось
Если сервер не сумел определить кодировку клиента, то документ будет отдан в
кодировке, определенной директивой
CharsetDefault.
Если CharsetDefault не указана, то будет использован charset, описанный
первым в директиве CharsetPriority.
SSI
Т.к. все директивы (кроме CharsetDecl и CharsetRecodeTable) могут
быть указаны где угодно, то это позволяет хранить документы в любой смеси
кодировок. Некоторые осложнения могут вызвать ServerSideIncludes. Правило простое
- на файл (в том числе включаемый через SSI) действуют правила той директории, где
он физически находится.
HTTP-заголовок Content-Type: text/html; charset=...
На выдачу сервером ; charset=CharsetName в заголовке
Content-Type: влияет установлена ли директива
CharsetMatchLanguage.
Если она установлена в On, то charest=... выдается при соблюдении
таких трех условий одновременно:
- Броузер клиента не является
"Bad Agent"
- Опция MultiViews (поддержка многоязыковой выдачи) включена (On)
- Язык документа, описанный через директиву AddLanguage, совпадает
с языком Charset, описанным директивой
CharsetDecl.
Это поведение, как и директива CharsetMatchLanguage, включены по умолчанию
в версиях PL18 и выше. В версии PL17 и более старых это было единственным
возможным поведением.
Такой режим удобен в том случае, если вы поддерживаете многоязыковый WWW-сервер.
В самом деле, выдавать charset=koi8-r для документа на английском языке
не только бессмысленно, но и вредно (например, у Lynx версий 2.5 и выше
от этого едет крыша т.к. для корректной поддержки русского Lynx нужно сначала
настроить).
Если опция CharsetMatchLanguage выключена (Off), то charset=....
выдается для всех документов.
[Server Home] [Next Page]