Автор: Ник Кью (Nick Kew)
Перевод: ApacheDev.ru
Оригинал статьи
Обработка НТТР запросов это основная задача в большинстве сетевых
программ. В этой статье мы расскажем об обработке запросов в Apache, и
о том, как модули могут вставлять собственные хуки в обработку запроса
при создании различных прикладных программ и компонентов. Статья
должна помочь разработчикам в освоении работы с модулями Apache, и
дать вам необходимые знания для лучшей работы с документированным API
и кодом Apache.
Введение
В архитектуру Apache входит: простое ядро, платформо-зависимый уровень
(APR), и модули. Любое приложение для Apache - даже простейшее,
обсуживающее "дефолтовую" страницу Apache "It worked" - использует
несколько модулей. Пользователи Apache не нуждаются в знании этого, но
для разработчика программ, понимание модулей и API модуля Apache
является ключом к работе с Apache. Большинство, но не все модули,
связаны с различными аспектами обработки НТТР запроса. Достаточно
редко встречается, что модулю необходимо работать с каждым аспектом
НТТР: как это делает httpd (Apache). Преимущество модульного подхода
состоит в том, что он позволяет фокусировать модуль на специфическую
задачу, игнорируя при этом другие аспекты НТТР, не касающиеся данной
задачи.
В этой статье мы расскажем об архитектуре обработки запроса в Apache,
и покажем, как модуль может перехватить контроль над различными
частями цикла обработки запроса.
Генерация контента
Простейшая формулировка веб-сервера - это программа, ожидающая НТТР
запросы и возвращающая ответы, при получении запроса. Это основная
задача в Apache, так называемое ядро веб-сервера. Для каждого HTTP
запроса должен запускаться генератор контента. Некоторые модули могут
регистрировать генераторы контента, определяя функции, ссылающиеся на
обработчик, который может быть сконфигурирован директивами SetHandler
или AddHandler в httpd.conf. Те запросы, для которых не
предоставляется генератор некоторого модуля, обрабатываются
стандартным генератором, который просто возвращает запрошенный файл
напрямую из файловой системы. Модули, которые реализуют один или более
генераторов контента, известны как генераторы контента или
обрабатывающие модули.
Фазы обработки запроса
В принципе, генератор контента может использовать все функции
веб-сервера: например, CGI программа получает запрос и генерирует
ответ, и может получить полный контроль над тем, что случиться за это
время. Но, по аналогии с другими веб-серверами, Apache разбивает
запрос на разные фазы. Так, например, он проверяет, авторизован ли
пользователь для работы перед тем, как генератор контента выдаст
результат.
Вот несколько фаз обработки запроса до момента генерации контента. Они
используются для проверки и возможно изменений заголовков запроса, и
определяют что делать с запросом. Например:
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 описывается несколькими
(необязательно) полями данных и функциями:
Функция модуля, которая создает хуки обработки запросов, последняя в
этой структуре:
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 немного
другой:
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 обновляется для
каждого запроса, и сохраняет данные запроса между фазами обработки
текущего запроса.
899 Прочтений • [Архитектура сервера Apache. Механизм модулей. (apache web module)] [08.05.2012] [Комментариев: 0]