Apache. Документация на русском


Разделы:   1    2    3    4    5    6    7    8    9    10      11      12    13    14    15    16  

Раздел 11. Документация для разработчиков

Пункты:   214    215    216    217      218      219    220    221    222    223  

 <         > 
  RU            EN  

Пункт 218. Хук-функции Apache 2.x

Этот документ все еще находится в разработке и может быть частично устаревшим.

В общем, функция ловушки — это функция, которую HTTP-сервер Apache будет вызывать в какой-то момент во время обработки запроса. Модули могут предоставлять функции, которые вызываются, и указывать, когда они вызываются по сравнению с другими модулями.

Основные крючки

Основные модули httpd предлагают заранее определенный список ловушек, используемых на стандартной фазе обработки запросов. Создание нового хука откроет функцию, которая его реализует (см. разделы ниже), но важно понимать, что вы не будете расширять основные хуки httpd. Их присутствие и порядок в обработке запросов на самом деле являются следствием того, как они вызываются server/request.c (см. этот раздел для обзора). Основные хуки перечислены в документации doxygen.

Прежде чем продолжить, настоятельно рекомендуется прочитать руководство по разработке модулей и обработке запросов.

Создание функции ловушки

Чтобы создать новый хук, необходимо сделать четыре вещи:

Объявите функцию ловушки

Используйте AP_DECLARE_HOOK макрос, которому нужно указать возвращаемый тип функции ловушки, имя ловушки и аргументы. Например, если хук возвращает a int и принимает a request_rec * и an int и вызывается do_something , то объявите его следующим образом:

 AP_DECLARE_HOOK(int, do_something, (request_rec *r, int n)) 

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

Создайте структуру крючка

Каждый исходный файл, который экспортирует ловушку, имеет частную структуру, которая используется для записи функций модуля, использующих ловушку. Это объявляется следующим образом:

 APR_HOOK_STRUCT(
 APR_HOOK_LINK(сделать что-нибудь)
 ...
) 

Реализовать вызывающий хук

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

Пустые крючки

Если возвращаемое значение хука равно void , то вызываются все хуки, а вызывающий объект реализован следующим образом:

 AP_IMPLEMENT_HOOK_VOID(do_something, (request_rec *r, int n), (r, n)) 

Второй и третий аргументы — это объявление фиктивного аргумента и фиктивные аргументы, поскольку они будут использоваться при вызове хука. Другими словами, этот макрос расширяется примерно так:

 недействительным ap_run_do_something (request_rec * r, int n)
{
 ...
 сделать_что-то (г, п);
} 

Хуки, возвращающие значение

Если хук возвращает значение, то его можно запустить до первого хука, который делает что-то интересное, например:

 AP_IMPLEMENT_HOOK_RUN_FIRST(int, do_something, (request_rec *r, int n), (r, n), ОТКЛОНЕН) 

Первый хук, который не возвращает значение, DECLINED останавливает цикл, и его возвращаемое значение возвращается от вызывающего хук. Обратите внимание, что DECLINED это традиционное возвращаемое значение хука, означающее «Я ничего не делал», но оно может быть любым, которое вам подходит.

В качестве альтернативы все хуки могут выполняться до тех пор, пока не произойдет ошибка. Это сводится к разрешению двух возвращаемых значений, одно из которых означает «я что-то сделал, и все было в порядке», а другое означает «я ничего не сделал». Первая функция, которая возвращает значение, отличное от одного из этих двух, останавливает цикл, и ее возвращаемое значение является возвращаемым значением. Объявите их так:

 AP_IMPLEMENT_HOOK_RUN_ALL(int, do_something, (request_rec *r, int n), (r, n), OK, ОТКЛОНЕН) 

Опять же, OK и DECLINED это традиционные ценности. Вы можете использовать то, что хотите.

Позвоните вызывающим абонентам

В соответствующие моменты в коде вызовите вызывающий хук, например:

 инт н, рет;
запрос_рек *r;
ret=ap_run_do_something(r, n); 

Зацепить крючок

Модуль, который хочет вызвать хук, должен сделать две вещи.

Реализовать функцию ловушки

Включите соответствующий заголовок и определите статическую функцию правильного типа:

 статический интервал my_something_doer (request_rec * r, int n)
{
 ...
 вернуть ОК;
} 

Добавить функцию регистрации хука

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

 статическая пустота my_register_hooks()
{
 ap_hook_do_something(my_something_doer, NULL, NULL, APR_HOOK_MIDDLE);
}
режим MODULE_VAR_EXPORT my_module =
{
 ...
 my_register_hooks /* регистрация хуков */
}; 

Управление порядком вызова хука

В приведенном выше примере мы не использовали три аргумента в функции регистрации хука, которые управляют порядком вызова всех функций, зарегистрированных в хуке. Для этого есть два механизма. Первый, довольно грубый, метод позволяет нам примерно указать, где запускается хук по отношению к другим модулям. Последний аргумент контролирует это. Возможны три значения: APR_HOOK_FIRST , APR_HOOK_MIDDLE и APR_HOOK_LAST .

Все модули, использующие какое-либо конкретное значение, могут запускаться в любом порядке относительно друг друга, но, конечно, все модули, использующие, APR_HOOK_FIRST будут запускаться раньше APR_HOOK_MIDDLE , чем перед APR_HOOK_LAST . Модули, которым все равно, когда они запускаются, должны использовать APR_HOOK_MIDDLE . Эти значения разнесены, так что такие позиции APR_HOOK_FIRST-2 можно перехватывать немного раньше, чем другие функции.

Обратите внимание, что есть еще два значения APR_HOOK_REALLY_FIRST и APR_HOOK_REALLY_LAST . Их должен использовать только экспортер крючков.

Другой метод позволяет более точно контролировать. Когда модуль знает, что он должен быть запущен до (или после) некоторых других модулей, он может указать их по имени. Второй (третий) аргумент — это завершающийся NULL массив строк, состоящий из имен модулей, которые должны быть запущены до (после) текущего модуля. Например, предположим, что мы хотим, чтобы «mod_xyz.c» и «mod_abc.c» запускались раньше, чем мы, тогда мы бы подключились следующим образом:

 статическая пустота register_hooks()
{
 static const char * const aszPre[] = { "mod_xyz.c", "mod_abc.c", NULL };
 ap_hook_do_something(my_something_doer, aszPre, NULL, APR_HOOK_MIDDLE);
} 

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



 <         > 

Пункты:   214    215    216    217      218      219    220    221    222    223  

Рейтинг@Mail.ru