Взаимодействие модулей Apache с файлами конфигурации (httpd.conf и .htaccess)


Большинство модулей от администраторов и пользователей требуют некоторой настройки. Системные администраторы конфигурируют Apache, используя httpd.conf, а пользователи (авторы) используют файлы .htaccess. Модулями можно управлять с помощью директив конфигурации, которые также задаются в этих файлах.
В этой статье мы покажем, как в модуле использовать директивы конфигурации, а также как работать с директивами других модулей.

Основы конфигурации модулей

С точки зрения системного администратора есть несколько видов директив. Они могут быть классифицированы в соответствии с их областями действия. То есть некоторые директивы распространяют свое действие на весь сервер, тогда как другие действуют только внутри некоторых границ, таких как <VirtualHost> или <Directory>.

Директивы также могут переопределять значения друг друга. Например, директива внутри секции <Directory> переопределяет директиву вне этой секции. В большинстве случаев это приводит к рекурсивной обработке секций, даже не смотря на то, что они используются разными модулями с совершенно разным поведением.
Вот стандартные контексты конфигурации, используемые в Apache:
Главная конфигурация (Main Config)
Директивы этого контекста находятся в файле httpd.conf, но не внутри какой-либо секции. Применяются глобально, кроме тех случаев, где они переопределены. Такие директивы подходят для стандартных настроек системы, таких как MIME-типов, а также для тех, которые используются только при запуске сервера, например список загружаемых модулей. Большинство директив можно использовать в данном контексте.
Конфигурация виртуального хоста (Virtual Host)
Каждый виртуальный хост имеет свою серверную конфигурацию, установленную в секции <VirtualHost>. Директивы, используемые в главной конфигурации, можно использовать и на этом уровне, а также наоборот.
Конфигурация каталога (Directory)
Секции <Directory>, <Files> и <Location> могут задавать многоуровневую иерархию конфигураций. Это самые используемые контексты конфигурации. Для краткости мы рассмотрим их вместе, как иерархию конфигураций каталогов.
.htaccess
.htaccess - это дополнение к иерархии каталогов, с помощью которого сервер разрешает вносить авторам свои значения директив, конечно, если доступ на это (AllowOverride) разрешен администратором сервера.
Однако запомните, что контексты это не всегда то же самое, что и секции конфигурации. Так, например, модули могут создавать для себя свои собственные секции: например, mod_access создает секцию <Limits>, а mod_perl создает секцию <Perl>.

Структуры данных конфигурации

Как рассказано выше, есть две различные иерархии в директивах конфигурации: серверы (VirtualHost) и каталоги (Directory), поэтому существуют две разные структуры данных: конфигурация сервера (per-server config) и конфигурация каталога (per-directory config). У каждого модуля есть собственные указатели на эти структуры, хотя модули редко используют их одновременно.
Конфигурация сервера хранится в структуре server_rec, которая создается для каждого виртуального хоста при запуске сервера. Конфигурация каталога хранится в структуре request_rec и создается для конкретного каталога функциями слияния конфигураций при каждом запросе (об этом ниже).

Управление конфигурацией модуля

Не менее пяти из шести используемых элементов структуры модуля Apache предназначены для конфигурации:
module my_module = {
STANDARD20_MODULE_STUFF,
my_create_dir_conf, /* Создание конфигурации каталога */
my_merge_dir_conf, /* Слияние конфигураций каталогов */
my_create_svr_conf, /* Создание конфигурации сервера */
my_merge_svr_conf, /* Слияние конфигураций серверов */
my_cmds, /* Директивы конфигурации */
my_hooks
};
Каждый модуль сам определяет собственные структуры конфигурации. После того, как структуры определены, модуль должен реализовать для них функции выделения памяти и инициализации:
typedef struct {
/* Поля структуры конфигурации сервера (хоста) */
}my_svr_cfg;
static void* my_create_svr_conf(apr_pool_t* pool, server_rec* svr) {
my_svr_cfg* svr = apr_pcalloc(pool, sizeof(my_svr_cfg));
/* Инициализация полей svr */
return svr;
}
typedef struct {
/* Поля структуры конфигурации каталога */
}my_dir_cfg;
static void* my_create_dir_conf(apr_pool_t* pool, char* x) {
my_dir_cfg* dir = apr_pcalloc(pool, sizeof(my_dir_cfg));
/* Инициализация полей dir */
return dir;
}
Вот все, что необходимо сделать для создания структур конфигурации. Далее Apache будет использовать результат работы этих функций. Теперь доступ к значениям этих структур может быть получен в любое время через указатели server_rec и request_rec:
my_svr_cfg* svr = ap_get_module_config(s->module_config, &my_module) ;
my_dir_cfg* dir = ap_get_module_config(r->per_dir_config, &my_module) ;

Создание директив конфигурации

Выше был описан массив my_cmds, который хранит все директивы, обрабатываемые данным модулем. Обычно директивы задаются с помощью макросов, определенных в файле http_config.h.
Например:
static const cmd_rec my_cmds[] = {
AP_INIT_TAKE1(“MyFirstDirective”, my_first_cmd_func, my_ptr,
OR_ALL, “Это моя первая директива”),
/* Другие директивы модуля */
{ NULL }
};
Макрос AP_INIT_TAKE1 - один из многих подобных макросов для определения директив модуля. Все они имеют одинаковый прототип со следующими аргументами:
  • Имя директивы.
  • Функция обработки этой директивы.
  • Указатель на структуру данных (обычно NULL).
  • Область действия директивы.
  • Краткое описание директивы.

Функции конфигурации

Неотъемлемой частью каждой директивы является обрабатывающая ее функция. Обычно это функция, устанавливающая некоторые поля одной из структур конфигурации. Прототип макроса AP_INIT_TAKE1 одинаковый, вне зависимости от того, для какой конфигурации мы создаем директиву: каталога или сервера:
const char* my_first_cmd_func(cmd_parms* cmd, void* cfg, const char* arg)
Аргумент cmd ссылается на структуру cmd_parms, поля которой используются Apache и модулями. Вот поля, представляющие интерес:
  • void *info - содержит my_ptr из макроса создания директивы.
  • apr_pool_t *pool - пул для долговременного хранения ресурсов.
  • apr_pool_t *temp_pool - пул для временного хранения ресурсов.
  • server_rec *server - структура данных конфигурации сервера.
Конфигурацию каталога можно получить из аргумента cfg, а конфигурацию сервера из server_rec. Аргумент arg содержит значение обрабатываемой директивы.

Типы функций конфигурации

В примере, приведенном выше, мы использовали макрос AP_INIT_TAKE1, который предназначен для директивы, имеющей один строковый аргумент. Это один из множества подобных макросов, определенных в http_config.h:
  • AP_INIT_NO_ARGS (без аргументов)
  • AP_INIT_FLAG (один флаговый аргумент)
  • AP_INIT_TAKE1 (один строковый аргумент)
  • AP_INIT_TAKE2, AP_INIT_TAKE3, AP_INIT_TAKE12 и т.д. - директивы с различным числом строковых аргументов.
  • AP_INIT_ITERATE (функция вызывается повторно для произвольного количества произвольных аргументов)
  • AP_INIT_ITERATE2 (функция вызывается повторно для двух аргументов)
  • AP_INIT_RAW_ARGS (функция вызывается для всех аргументов сразу)
Такой подход дает авторам модулей выбор, как готовых прототипов для заданного количества аргументов, так и возможность ручной обработки макросом RAW_ARGS. Модули, использующие RAW_ARGS, получают аргументы, циклически вызывая функцию ap_getword_conf до тех пор, пока она не вернет NULL.

Области конфигурации

В вышеприведенном примере мы использовали OR_ALL, что означает, что директива MyFirstDirective может использоваться в любом месте файла httpd.conf или в любом .htaccess файле (если .htaccess разрешены на сервере). Вот другие значения, которые мы можем использовать:
  • Флаг RSRC_CONF определяет верхний уровень httpd.conf или контекст VirtualHost. Все директивы, используемые в блоке VirtualHost, должны использовать этот флаг.
  • ACCESS_CONF - уровень httpd.conf в контексте каталога. Наиболее подходящее значение для директив контекста каталога, а если использовать вместе (используя OR) с RSRC_CONF, то и для любого места в httpd.conf.
  • OR_LIMIT, OR_OPTIONS, OR_FILEINFO, OR_AUTHCFG, OR_INDEXES - разрешают использовать директивы в .htaccess в соответствии с настройками AllowOverride.

Другие функции конфигурации

В общем случае, как в примере выше, необходимо создавать собственные функции для обработки директивы. Но это не всегда обязательно. В случае с простой директивой, которая только устанавливает значение некоторого поля в конфигурации каталога, мы можем использовать одну из следующих функций: ap_set_string_slot, ap_set_string_slot_lower, ap_set_int_slot, ap_set_flag_slot, ap_set_file_slot, в зависимости от типа поля структуры. Чтобы задать значение этого поля, Вы должны передать указатель на него, как, например:
AP_INIT_TAKE1(“MySimpleDirective”, ap_set_int_slot,
(void*)APR_OFFSETOF(my_dir_cfg, myintvar),
OR_ALL, “Установка myintvar”);
Где myintvar - это целочисленное поле структуры my_dir_config

Иерархия конфигураций

Теперь мы разобрались с тем, как создавать структуры конфигураций и поработали с ними. Последняя тема, которую нам надо рассмотреть, это создание и работа с иерархией конфигураций, а именно, как директивы, установленные на разных уровнях, будут взаимодействовать друг с другом. Эту задачу решают функции объединения, определенные в структуре модуля.
Функции объединения вызываются всякий раз, когда одинаковые директивы существуют более чем на одном уровне, начиная с верхнего уровня httpd.conf. В случае с конфигурацией каталога может быть неограниченное количество уровней, и таким образом функция объединения вызывается несколько раз, объединяя файлы .htaccess и секции в httpd.conf.
Указатели на функции объединения в структуре модуля могут иметь значения NULL. В этом случае все директивы в нижних (по уровню) секциях игнорируются, поэтому инкрементная сборка конфигурации невозможна.
Обычно функции объединения используются в тех случаях, когда необходимо использовать директивы, которые заданы в секциях на самых нижних уровнях, но при этом наследовать директивы с верхних уровней. Рассмотрим следующий пример:
typedef struct {
int a, b, c;
}my_dir_cfg;
С директивами, устанавливающими значение каждого поля и со следующей конфигурацией:
<Location />
SetMyA 123
SetMyC 321
</Location>
<Location /somewhere/>
SetMyB 456
</Location>
<Location /somewhere/else/again/>
SetMyC 789
</Location>
Самый вложенный каталог - это /somewhere/else/again/, поэтому нам надо установить для с значение 789, а значения a и b унаследовать от значений предыдущих уровней. Для этого нам нужна функция объединения, которая имеет вид:
static void* my_merge_dir_conf(apr_pool_t* pool, void* BASE, void* ADD) {
my_dir_cfg* base = BASE;
my_dir_cfg* add = ADD;
my_dir_cfg* conf = apr_palloc(pool, sizeof(my_dir_cfg));
conf->a = ( add->a == UNSET ) ? base->a : add->a;
conf->b = ( add->b == UNSET ) ? base->b : add->b;
conf->c = ( add->c == UNSET ) ? base->c : add->c;
return conf;
}
Для оптимизации функции мы присвоим константе UNSET некоторое неиспользуемое значение (например “-1″, если все наши значения должны быть положительными) и инициализируем все поля my_dir_cfg этим значением в функции create_config. Теперь наша конфигурация обработается в следующем порядке:
  1. На верхнем уровне a принимает значение 123, а c 321.
  2. Первое объединение присваивает b значение 456. Так как a и c не заданы на этом уровне, то они наследуют предыдущие значения.
  3. На уровне /somewhere/else/ директив нет, поэтому этот уровень просто наследуется от вышележащего /somewhere/ без необходимости какого-либо слияния.
  4. Второе объединение задает новое значение c, переопределяя предыдущее значение и наследуя значения a и b. Итак, в результате мы имеем a=123, b=456, с=789.
Очевидно, что это тривиальная функция объединения. Обычно необходимо сделать что-то более интересное: например, объединить сложные структуры или работать в ситуации, когда нет четкого значения UNSET для принятия решения.
Это почти все, что можно сказать о конфигурации модулей Apache. Надеюсь, что Вам понравился данный материал. Если у Вас остались вопросы, то отправляйте их на info@apachedev.ru Я обязательно отвечу на них.
Автор: Ник Кью (Nick Kew)
Перевод: Сипягин Максим
Оригинал документа (en)

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • News2.ru
  • NewsLand.ru
  • del.icio.us
  • BobrDobr.ru
  • Ma.gnolia
  • Digg
  • Reddit
  • Technorati
  • Slashdot
  • Netscape
  • DZone
  • ThisNext
  • Furl
  • YahooMyWeb
Опубликовано в: Разработка модулей Февраль 12, 2006

6 Комментариев »

  1. простно и понятно

    Комментарий от jobs — Февраль 7, 2008 @ 9:33 am

  2. ДА!! СУПЕР!!! СПАСИБО!!!!
    ____________________
    www.specmachines.ru/

    Комментарий от андрюха — Август 29, 2008 @ 12:07 pm

  3. neponyatno

    Комментарий от Пётр — Октябрь 18, 2008 @ 5:54 pm

  4. +1

    Комментарий от Тимур — Октябрь 18, 2008 @ 5:55 pm

  5. буду неоригинальна:
    +3

    Комментарий от Амалия — Октябрь 18, 2008 @ 5:55 pm

  6. Нет ничего конкретного, хотелось бы примеров…

    Комментарий от Alex — Февраль 6, 2009 @ 2:23 am

Оставить комментарий

You must be logged in to post a comment.

Работает на WordPress