Обработка запросов в Apache


Обработка НТТР запросов является основной задачей для большинства сетевых программ. В этой статье мы расскажем об обработке запросов в Apache и о том, как модули могут принять в ней посильное участие. Статья должна помочь разработчикам в освоении работы с модулями Apache и дать Вам необходимые знания для лучшей работы с API и кодом Apache.

Введение


В архитектуру Apache входит: ядро, платформо-зависимый уровень (APR) и модули. Любое приложение на базе Apache, даже простейшее, обсуживающее стандартную страницу Apache “It worked”, использует несколько модулей. Пользователям Apache не обязательно знать это, но для разработчика понимание модулей и API 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 2.0 - это трансформация его из простого веб-сервера (как Apache 1.3 и другие) в мощную платформу, представляющую собой цепочку фильтров. Она может быть изображена как ось данных (см. рис 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. Так поступают генератор контента и фильтры, также себя ведет и обработчик ведения логов. Для полного описания этой структуры смотрите заголовочный файл 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.
  • Другие структуры данных ядра доступны как: r->connection (структура соединения), r->server (структура сервера) и т.п.
  • Дополнительное поле request_config обновляется для каждого запроса и используется для хранения данных запроса между фазами обработки текущего запроса.
Автор: Ник Кью (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
Опубликовано в: Архитектура Февраль 4, 2006

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

Комментариев нет.

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

You must be logged in to post a comment.

Работает на WordPress