Russian Apache Switch to English
Switch to Russian koi8-r
windows=1251
cp-866
iso8859-5
Russian Apache Как это работает Рекоммендации Где взять Как установить Как настроить Статус и поддержка
Краткий обзор FAQ Список рассылки Благодарности Поиск по серверу Powered by Russian Apache
Некоторые рекомендации

для версий начиная с PL18.
В этом документе приведены примеры наиболее распространенных конфигураций, применяемых на практике. По-хорошему, он не очень нужен т.к. все тонкости упомянуты в описании директив конфигурации и описании принципов работы сервера. Однако наличие готовых примеров сильно уменьшает поток писем с просьбой о помощи.

В конце документа приведено описание переменных окружения, которые могут быть использованы в CGI-скриптах и Russian Apache API - функций и макросов, которые могут быть использованы при написании собственных модулей. Для модулей на Perl предусмотрен Russian Apache Perl API.

Этот документ переработан с учетом новых директив конфигурации и нового поведения сервера, появившихся в версиях PL18-PL28, пользователи старых (PL12-PL16) версий могут использовать старую версию этого документа, хотя она и несколько невнятная.

Общая идея всех приводимых ниже примеров конфигурации совершенно одинакова:

  1. Имеется "основной" сервер (www.company.ru), который автоматически распознает кодировку клиента по Accept-Charset и User-Agent. В большинстве случаев он будет правильно распознавать кодировку клиента, но получаемые таким образом документы не могут быть кэшированы (т.к. одному URL соответствует различный content в различных ситуациях), что осложняет работу по медленным каналам.
  2. Для каждого документа основного сервера имеется некоторое количество (по числу поддерживаемых кодировок) "виртуальных URL". Содержимое этих URL одинаковое, а кодировка не зависит от User-Agent (но зависит от Accept-Charset).
    Возможны несколько вариантов создания таких "виртуальных URL" - виртуальные директории, виртуальные сервера с разными hostname (см. также пример упрощенной конфигурации для Apache-1.3) и виртуальные сервера, разнесенные по номерам портов. Каждый способ имеет свои недостатки и преимущества, выбор нужного метода остается целиком на совести администратора. Во всех трех случаях, документ полученный с URL с "явным выбором кодировки" может быть кэширован как HTTP/1.0, так и HTTP/1.1-совместимыми кэшами (т.е. заголовок Expires: не ставится, а в заголовке Vary: остается только accept-charset).

    Начиная с Apache-1.3.1 RUS PL26, можно использовать внешние модули определяющие кодировку клиента по каким-либо параметрам и передающие название требуемой кодировки в mod_charset через переменную окружения. См. пример использования этой возможности совместно с RewriteModule.


Пример конфигурации основного сервера имеется в комплекте "Russian Apache", далее в этом документе мы рассмотрим только изменения и дополнения, которые нужно сделать в конфигурации в том или ином случае.

Выбор кодировки по виртуальной директории
При этом способе выбора кодировки, каждому документу соответствует несколько URL:
  1. http://www.domain/file.html - автоматический выбор кодировки
  2. http://www.domain/charset-name/file.html (например - http://www.domain/koi8-r/file.html) - кодировка задается префиксом директории.
Для того, чтобы сервер работал в таком режиме, нужно либо создать псевдо-директории как symlink:
ln -s /www/root/htdocs /www/root/htdocs/koi8-r
etc
  
либо воспользоваться директивой Alias:
Alias /koi8-r /your/www/root/htdocs
# etc
  

Основное достоинство этого метода заключается в его простоте, а основной недостаток состоит в том, что все ссылки между документами должны быть с относительным путем. Т.е. вместо <A HREF="/some">, нужно писать что-то вроде <A HREF="../../../some"> по той причине, что при переходе из документа /koi8-r/file.html на ссылку /some произойдет переключение на автоматическую перекодировку (для сохранения явного выбора кодировки переходить нужно на /koi8-r/some т.е. на ../some). Необходимая строгость совпадения имени кодировки и имени директории задается директивой CharsetStrictURIMatch.

Выбор кодировки по имени виртуального сервера
При этом способе явного задания кодировки, соответствующие URL будут такими: Существуют как минимум два способа настройки сервера для работы в таком режиме:
  1. Если первые символы (либо host part - см директиву CharsetStrictURIMatch hostname совпадают с названием (или alias) какого-либо charset, то (при настройке CharsetSelectionOrder по умолчанию) сервером будет выбран именно этот charset. Пример конфигурации:
    <VirtualHost win-www.domain.ru>
    # вообще-говоря, никаких дополнительных директив не нужно
    </VirtualHost>
        
  2. В-принципе, имя виртуального хоста может быть совершенно произвольным. В этом случае можно использовать такую конфигурацию:
    <VirtualHost any.domain.ru>
    CharsetSelectionOrder
    CharsetDefault windows-1251 # например
    </VirtualHost>
        
    В этом примере использована пустая директива CharsetSelectionOrderт.е. все способы автоматического определения кодировки (Portnumber, Hostname, Dirprefix, Useragent) выключены и документ отдается в default-кодировке. Но в случае, если клиентская программа включила в запрос заголовок Accept-Charset и требуемый charset известен серверу, то будет удовлетворено требование клиента. Всякое другое поведение противоречит стандартам HTTP.

Виртуальные сервера и DNS

Если вы ожидаете, что на ваш сервер будут ходить HTTP/1.0-совместимые клиенты, то каждый виртуальный сервер должен иметь свой IP-адрес. Протокол HTTP/1.1 может обходиться без отдельных IP-адресов т.к. в каждом запросе должен присутствовать обязательный заголовок Host:, сообщающий серверу к какому именно серверу обращается клиент. Заголовок Host ставят и некоторые HTTP/1.0 клиенты, но это не является обязательным их свойством.

Как следствие, для использования механизма виртуальных серверов, DNS-зона для домена должна содержать записи типа A, а обратная (address->hostname) зона - корректные записи типа PTR. Корректная обратная зона необходима Apache-1.2.x для правильной обработки HTTP/1.0 (без Host:) запросов. Версии 1.1.x были менее требовательны к этому. При этом, Apache-1.2.x (как с правками, так и без) делает все обращения к DNS в момент startup (или переконфигурации), поэтому записи в DNS должны быть корректными на момент старта сервера (я бы не писал про это так много, но это - достаточно распространенные проблемы).

Более подробно об особенностях работы Apache с виртуальными серверами можно прочитать прямо на WWW-сервере проекта Apache.

Выбор кодировки по имени виртуального сервера - упрощенный вариант для Apache-1.3
В Apache 1.3 появилась очень хорошая возможность указать виртуальному серверу принимать все запросы, hostname которых подпадает под определенную маску. Делается это командой ServerAlias *.www.youcompany.com. Начиная с Russian Apache Pl26.0, в директиве CharsetSelectionOrder можно задать параметр URIHostname, который включает возможность сравнения имени hostname к которому был реальный запрос с именем какого-либо charset (правило Hostname сравнивает с именем сервера, написанным в директиве <VirtualHost>) Пример:
<VirtualHost 1.2.3.4>
ServerAlias	*.www.foo.net
</VirtualHost>
При обращениях к windows-1251.www.foo.net и к koi8-r.www.foo.net клиенту будет отдана соответствующая кодировка. Естественно, оба хоста должны иметь соответствующие записи в DNS (достаточно CNAME).

Достоинства и недостатки схемы с <VirtualHost>

Достоинства очевидны - все ссылки (<A HREF=) в документе могут быть абсолютными. Недостатки тоже очевидны - пока существуют HTTP/1.0-совместимые клиенты, не ставящие заголовок Host:, для каждого виртуального сервера необходим свой IP-адрес и корректная настройка зон в DNS (т.е. нужен или доступ к DNS или доступ к понимающему проблему администратору). Это не является большой проблемой для "официального webmaster'а", но может являться проблемой для администраторов персональных серверов.

Выбор кодировки по номеру порта
При этом способе явного задания кодировки, соответствующие URL будут такими:
  1. http://www.domain/file.html - автоматический выбор кодировки
  2. http://www.domain:port/file.html (например - http://www.domain:8001/file.html) - кодировка задается номером порта в URL (это делается директивой CharsetByPort и/или явной настройкой <VirtualHost>.
Для того, чтобы сервер "слушал" (listen(2)) более чем на одном TCP-порту, необходимо использовать директиву Listen Portnumber, например так:
Listen 80
Listen 8100
Listen 8101
# и так далее
  
Директива Listen 80 необходима т.к. наличие директивы Listen выключает директиву Port (точнее, при наличии Listen, Port отвечает только за содержимое CGI-переменной SERVER_PORT).

Для того, чтобы связать какую-то определенную кодировку с номером порта, существует по меньшей мере 2 способа:

  1. Использование директивы CharsetByPort:
    Listen 80
    Listen 8100
    Listen 8101
    CharsetByPort koi8-r 8100
    CharsetByPort windows-1251 8101
    CharsetSelectionOrder Portnumber Hostname Dirprefix Useragent #default value
        
    При такой конфигурации кодировка будет выбираться по номеру порта для всех виртуальных серверов.
  2. Кодировку можно задать прямо в описании виртуального сервера:
    Listen 80
    Listen 8100
    Listen 8101
    <VirtualHost some.domain:8100>
    CharsetDefault koi8-r
    CharsetSelectionOrder # опять пустая директива, см. выше
    </VirtualHost>
        
    В обоих случаях для каждой пары hostname:port можно переопределить поведение; более того, все директивы могут встречаться и в файлах .htaccess т.е. возможности для создания запутанной структуры сервера просто безграничны.

Некоторые особенности работы с перекодировкой по портам

  1. При обращении "к директории" с пропущенным trailing slash в URL (например http://www.server.ru/directory), mod_dir из apache_1.2.x делает Redirect на http://www.server.ru/directory/. Все было бы хорошо, но в случае недостаточно полно сконфигурированного сервера, код из mod_dir не ставит правильный номер порта. Так при обращении к http://www.server.ru:8000/directory клиенту будет выдан редирект на http://www.server.ru/directory/, что неприемлемо. "Лечение" этой особенности возможно несколькими способами: Наверное, первый из перечисленных способов - самый простой.
  2. Директивы класса Redirect (Redirect, RedirectTemp, RedirectPermanent) требуют задания последним параметром полного URL на который нужно делать редирект. Понятно, что при использовании перекодировки по номеру порта использование Redirect* неудобно или невозможно. Вместо этих директив предлагается использовать директиву CharsetSoftRedirect последний аргумент которой - URL относительно ServerRoot т.е. hostname сервера и порт будут подставлены на runtime и будут правильными

Достоинства схемы:

  1. Все ссылки в пределах сервера могут быть абсолютными.
  2. Не расходуются дефицитные IP-адреса.
Недостатки:
  1. При работе через фильтрующий firewall (packet filter) необходимо открывать большее число портов чем обычно. Это может стать проблемой в случае, когда администратор WWW и администратор firewall - разные люди.
  2. Так как "по сложившейся традиции" для WWW-серверов с явной перекодировкой по номеру порта используются порты с номером больше 1024 (чаще всего - 8000-800x, 8080-8080x и так далее), а такие порты на UNIX может открывать и непривилегированный пользователь, то возможны некоторые проблемы с security. Т.е. потенциальный "взломщик" может дождаться момента, когда основной сервер не запущен и запустить свой fake сервер на тех же портах. Это не является сколько-нибудь серьезной проблемой, но забывать об этом не следует (workaround - выбирать порты с номером меньшим 1024).
Использование выбора кодировки по портам вместе с директивой <VirtualHost>

Как выясняется, у администраторов WWW-серверов, желающих использовать такую схему работы, когда

часто возникает одна и та же проблема - при обращении к default-порту все абсолютно нормально, а при обращении к любому другому - показывается содержимое основного сервера (правда в желаемой кодировке).

Это поведение не является свойством "Russian Apache", а является "feature" Apache-1.2.x и описано в документации к оригинальному Apache. Для того, чтобы добиться желаемого поведения, директиву <VirtualHost> нужно использовать в виде

<VirtualHost www.some.domain:*>
  
т.к. по умолчанию директива <VirtualHost> "имеет отношение" только к порту, заданному директивой Port. Смотри также замечания выше.

Внимание. Apache-1.2.0...1.2.5 содержит ошибку при работе с "Host: -based" virtual hosts (т.е. работающими на одном IP-адресе), которая приводит к тому, что конструкции <VirtualHost host.domain> и <VirtualHost host.domain:*> эквивалентны т.е. <VirtualHost> не работает на портах иных, чем заданный директивой Port. Это явная ошибка, ее описание и патч уже отосланы Apache-Team, но пока это не починено в оригинальной версии можно пользоватьсяRussian Apache PL20.5 (или новее), где эта ошибка исправлена. Эта ошибка исправлена и в Apache-1.2.6.

Задание кодировки другими модулями
Начиная с версии PL26.0, Russian Apache может взаимодействовать с другими модулями определения кодировки клиента. При этом mod_charset будет заниматься только перекодировкой. Для этого "другие модули" должны установить переменную окружения FORCE_CHARSET в значение, равное имени одного из charset, известных Russian Apache (для Apache-hackers - переменная выбирается из таблицы r->subprocess_env). Это может делать любой модуль, он должен сработать раньше, чем mod_charset.

В поставке оригинального Apache-1.3 есть три модуля, которые могут устанавливать переменные окружения - mod_env, mod_setenvif и mod_rewrite. Первый из них неинтересен - он ставит заданные переменные всегда. Два других позволяют добиться функциональности, которой нет в mod_charset. Примеры: