В архітектуру Apache входить: просте ядро, від платформи залежний рівень (APR), і модулі. Будь-який додаток для Apache - навіть найпростіше, які обслуговуються «дефолтовая» сторінку Apache «It worked» - використовує кілька модулів. Користувачі Apache не потребують знанні цього, але для розробника програм, розуміння модулів і API модуля Apache є ключем до роботи з Apache. Більшість, але не всі модулі, пов'язані з різними аспектами обробки НТТР запиту. Досить рідко зустрічається, що модулю необхідно працювати з кожним аспектом НТТР: як це робить httpd (Apache). Перевага модульного підходу полягає в тому, що він дозволяє фокусувати модуль на специфічну задачу, ігноруючи при цьому інші аспекти НТТР, які не стосуються даного завдання.
У цій статті ми розповімо про архітектуру обробки запиту в Apache, і покажемо, як модуль може перехопити контроль над різними частинами циклу обробки запиту.
Найпростіша формулювання веб-сервера - це програма, яка очікує НТТР запити і повертає відповіді, при отриманні запиту. Це основне завдання в Apache, так зване ядро веб-сервера. Для кожного HTTP запиту повинен запускатися генератор контенту. Деякі модулі можуть реєструвати генератори контента, визначаючи функції, що посилаються на обробник, який може бути налаштований директивами SetHandler або AddHandler в httpd.conf. Ті запити, для яких не надається генератор деякого модуля, обробляються стандартним генератором, який просто повертає запитаний файл безпосередньо з файлової системи. Модулі, які реалізують один або більше генераторів контенту, відомі як генератори контента або обробні модулі.
Ось кілька фаз обробки запиту до моменту генерації контенту. Вони використовуються для перевірки і можливо змін заголовків запиту, і визначають що робити із запитом. наприклад:
URL запиту потрібно порівняти з даними конфігурації, щоб визначити, який генератор контенту повинен використовуватися.
Треба визначити файл, на який посилається URL запиту. URL може звертатися як до статистичного файлу, так і до CGI скрипту, або до чого-небудь ще, що може використовуватися для генерації контенту.
Якщо контент доступний, то mod_negotiation знайде ту версію ресурсу, яка краще підходить до налаштувань браузера. Наприклад, сторінки довідки Apache виводяться на тій мові, на якому надійшов запит від браузера.
Правила доступу та ідентифікації модулів перевіряються на відповідність правилам доступу сервера, і визначається, чи має право користувач отримати те, що він запросив.
mod_alias або mod_rewrite можуть змінити URL в запиті.
На додаток, є ще фаза логування запиту, яка виповнюється після того, як генератор контенту пошле браузеру відповідь.
Модуль може впровадити свої власні обробники в будь-який з цих хуков. Модулі, що обробляють дані на фазах до генерації контенту, відомі як модулі метаданих. Ті, які працюють з логування, відомі як модулі логування.
Що ми описали вище - це по суті архітектура будь-якого веб-сервера. Різниця лише в деталях, але фази обробки запиту: метаданние-> генератор контента-> логирование є загальними.
Головне нововведення в Apache 2 це трансформація його з простого веб-сервера (як Apache 1.3 та інші) в потужну платформу, що представляє собою ланцюжок фільтрів. Вона може бути зображено як вісь даних, перпендикулярна осі обробки запиту. Запитані дані можуть оброблений вхідними фільтрами до генератора контенту, а відповідь сервера може оброблений вихідними фільтрами до відправки клієнтові. Фільтри дозволяють зробити попередню фільтрацію і більш ефективно представити дані обробки, відокремлюючи ці фази від генерації контенту. Приклад фільтрів: включення на стороні сервера (SSI), XML і XSLT обробка, gzip компресія і шифрування (SSL).
Перед початком обговорення того, як модуль впроваджується в будь-стадії обробки запиту / даних, давайте зупинимося на одному моменті, який часто стає причиною плутанини серед початківців розробників модулів Apache: а саме-порядок обробки.
Ось обробки запиту лінійна: фази відбуваються в строгому порядку. Але плутанина виникне на осі даних. Для максимальної ефективності - порядок змінюється, тому генератор і фільтри не виконуються в строго заданій послідовності. Так, наприклад, в загальному, ви не зможете передати що-небудь у вхідний фільтр і очікувати отримання цього в генераторі або в вихідних фільтрах.
У центрі обробки знаходиться генератор контенту, який відповідає за отримання даних з стека вхідних фільтрів і поміщає дані в стек вихідних фільтрів. Коли генератор або фільтр потребують обробки запиту цілком, вони повинні зробити це до передачі даних вниз по ланцюжку (генератору або вихідним фільтрам), або до повернення даних назад вхідного фільтру.
Тепер у нас є загальне уявлення про обробку запиту в Apache, і ми можемо продовжити говорити про те, як модулі стають частиною цієї обробки. Структура модуля apache описується декількома (необов'язково) полями даних і функціями:
module AP_MODULE_DECLARE_DATA my_module = <
STANDARD20_MODULE_STUFF,
my_dir_conf,
my_dir_merge,
my_server_conf,
my_server_merge,
my_cmds,
my_hooks
>;
Функція модуля, яка створює хукі обробки запитів, остання в цій структурі:
static void my_hooks (apr_pool_t * pool) / * створення необхідних хуков обробки запиту * /
>
Залежно від того, в яких частинах запиту зацікавлений наш модуль, нам потрібно створити відповідні хукі. Наприклад, модуль, який реалізує генератор контенту (обробник), потребує хук обробки (handler hook), на зразок:
ap_hook_handler (my_handler, NULL, NULL, APR_HOOK_MIDDLE);
Тепер my_handler буде викликаний, коли обробка запиту дійде до фази генерації контенту. Хукі інших фаз запиту схожі; Також іноді використовують один з:
ap_hook_post_read_request Перший шанс для обробки запиту після його прийняття.
ap_hook_fixups Останній шанс обробки запиту перед генерацією контента.
ap_hook_log_transaction Хук логування.
Між хукамі post_read_request і fixups є кілька інших хуков, створених для специфічних цілей: наприклад модулі доступу і ідентифікації мають хукі перевірки доступу. Все хукі мають точно такий же вигляд, як і хук обробки. Для детальної інформації, дивіться http_config.h
Прототип обробника будь фази:
static int my_handler (request_rec * r) <
/* опрацювання запиту */
>
request_rec це головна структура даних apache, що зберігає всіх дані НТТР запиту.
Значення, що повертається my_handler може бути наступним:
OK
my_handler обробив запит успішно. Фаза обробки завершена.
DECLINED
my_handler не зацікавлений в запиті. Дозволимо іншим обробникам розібратися з ним.
Деякий НТТР код
Сталася помилка, поки оброблявся запит. Це змінює шлях обробки запиту: нормальна обробка припинена, і сервер замість повертає ErrorDocument.
Фільтри також реєструються в функціях my_hooks, але API трохи інший:
ap_register_output_filter ( «my-output-filter-name», my_output_filter,
NULL, AP_FTYPE_RESOURCE);
ap_register_input_filter ( «my-input-filter-name», my_input_filter,
NULL, AP_FTYPE_RESOURCE);
з наступними прототипами функцій фільтрів
static apr_status_t my_output_filter (ap_filter_t * f, apr_bucket_brigade * bb) / * Читання блоку даних, обробка і передача наступного фільтру * /
return APR_SUCCESS;
>
static apr_status_t my_input_filter (ap_filter_t * f, apr_bucket_brigade * bb,
ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes) <
/ * Отримання блоку від наступного фільтра, обробка, повернення блоку в bb * /
return APR_SUCCESS;
>
Функції фільтрів повертають APR_SUCCESS якщо все нормально, або явно, подібно перерахованим вище, або як код повернення від наступного фільтра через виклик ap_pass_brigade або ap_get_brigade. Документація API знаходиться в util_filter.h.
Центральна структура, яка описує НТТР запит - це request_rec. Вона створюється, коли Apache приймає запит, і вона надається всім функціям обробки запиту, як показано вище в прототипі my_handler. У фільтрі контенту, request_rec доступний як f-> r.
request_rec це величезна структура, яка містить, прямо або побічно, всі дані, необхідні в процесі обробки запиту. Будь-обробник метаданих працює через отримання і зміна полів в request_rec; так надходять генератор контенту і фільтри, також поводяться додаткові процеси I / О і обробник логування. Для повного опису, дивіться заголовки httpd.h.
Ми закінчуємо цю статтю, коротко розповівши про використання request_rec. Вам необхідно також подивитися на API або інші статті, де описані деталі використання цієї структури.
Ось невеликий список відповідей на типові запитання:
Пул запиту r-> pool доступний для всіх створених ресурсів і має час життя запиту.
Заголовки запиту і відповіді доступні в r-> headers_in і r-> headers_out відповідно. Вони мають тип apr_table_t і обробляються apr_table функціями, такі як apr_table_get і apr_table_set.
Поле обробника визначає, який обробник зараз в дії. Генератори контенту повинні перевіряти його і негайно повертати DECLINED, якщо він не підходить.
Поля input_filter і output_filter можуть бути використані як I / O дескриптори, тільки в модулі-фільтрі. Високо-рівневі I / O (перенесено з apache 1.x) доступні для генераторів контенту, але не для фільтрів.
Директиви конфігурації надаються в поле per_dir_config, і можуть бути отримані через використання ap_get_module_config (також ap_set_module_config, хоча це повинно бути дуже недоречно ст час обробки запиту).
Інші структури даних ядра доступні як r-> connection (структура сполуки), r-> server (структура сервера), і т.п. Їх конфігурації також доступні запитом.
Додаткове поле конфігурації request_config оновлюється для кожного запиту, і зберігає дані запиту між фазами обробки поточного запиту.