Написание фильтров для Apache 2.0


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

Эта статья описывает основные концепции фильтров Apache. В моей следующей статье я проведу Вас через процесс создания фильтра. В этой статье я также покажу Вам некоторые основы написания входных фильтров.

Стандартные фильтры


Для обеспечения работы механизма фильтров разработчики Apache рассматривают веб-страницы как блоки (chunk) информации. Разработчики сделали так, чтобы нас не беспокоило то, на что эти блоки похожи или то, как они хранятся на сервере. В терминологии фильтров Apache, каждый блок хранится в контейнере (bucket), а список контейнеров формирует бригаду (brigade). А список бригад в свою очередь формирует веб-документ. Фильтр работает с одной бригадой за раз, и для обработки всего документа вызывается повторно для каждой бригады. Такой подход позволяет серверу передавать данные клиенту блоками, не дожидаясь завершения обработки всего документа.
Основной дистрибутив сервера Apache 2.0 содержит несколько стандартных фильтров.
Первый это content_length_filter. Этот фильтр подсчитывает длину данных, отправляемых клиенту сервером, в байтах. Если при первом вызове фильтра ответ сервера недоступен в полном объеме, и, если протокол позволяет серверу отсылать ответ без заголовка content-length, тогда этот фильтр просто пропускает данные к следующему фильтру. Однако он все-таки продолжает подсчитывать длину для ведения логов.
Второй стандартный фильтр это header_filter. При первом вызове фильтр формирует заголовки и передает их следующему фильтру. После этого он передает само содержание веб-страницы. Это важный момент, потому что, если Вашему фильтру необходимо изменить заголовки, то он должен быть размещен до header_filter. Также он должен хранить все содержание страницы до тех пор, пока не закончит работать с заголовками. Когда же Ваш фильтр передает данные следующему фильтру в стеке, Вы тем самым сообщаете серверу Apache, что закончили работать с данными, и он может отсылать их клиенту.
Последним фильтром в выходной цепочке всегда является core_output_filter. Этот фильтр отвечает за отправку данных в сеть. Для оптимального использования пропускной способности сети Apache перед отправкой буферизирует данные по 9 KB. Тем не менее фильтры могут заставить Apache отправлять данные немедленно, путем очистки текущего стека фильтров.

Типы фильтров и их предназначения

Перед тем как фильтр сможет получать запросы, он должен быть зарегистрирован на сервере. Это делается функцией ap_register_output_filter. Эта функция вызывается с тремя аргументами: имя фильтра, указатель на функцию фильтра и тип фильтра.
ap_register_output_filter(“CONTENT_LENGTH”, ap_content_length_filter, AP_FTYPE_HTTP_HEADER);
Имя фильтра должно быть уникальным в пространстве имен сервера. Два фильтра не могут использовать одинаковую строку для своих имен. В связи с этим рекомендуется, чтобы имена фильтров обладали некоторой уникальной защитой имен (префиксами) для каждого модуля. Функция фильтра - это функция, которая должна быть добавлена в стек фильтров всякий раз при определении этого фильтра. В следующий раз мы рассмотрим эту функцию более подробно. Также должен быть определен тип фильтра. Каждый фильтр имеет связанный с ним тип. Это помогает Apache корректно упорядочивать фильтры в стеке. Ниже приведен список типов фильтров с их описанием:
  • AP_FTYPE_CONTENT Этот тип фильтров показывает, что фильтр будет использоваться для изменения содержания веб-страницы. Примеры фильтров этого типа: SSI или PHP.
  • AP_FTYPE_HTTP_HEADER Это специальный тип фильтра, который дает возможность модулям изменять заголовки. Все фильтры данного типа запускаются после AP_FTYPE_CONTENT фильтров. Примеры фильтров данного типа: content_length и http_header.
  • AP_FTYPE_TRANSCODE Тип фильтров, которые могут изменять способ отправки ответа клиенту, но не содержание этого ответа. Пример этого типа фильтров - фильтр chunking_filter, который разбивает ответ сервера на блоки. Все фильтры этого типа запускаются после AP_FTYPE_HTTP_HEADER фильтров.
  • AP_FTYPE_CONNECTION Фильтры этого типа используются для изменения способа интерпретации сервером HTTP данных. Эти фильтры не стоит использовать для изменения данных запроса или ответа, потому что они вызываются после фильтров AP_FTYPE_TRANSCODE, когда сервер уже создал заголовки для запроса и ответа. Пример этого типа фильтров - http_in фильтр, который разбивает составные запросы в одном соединении на отдельные запросы.
  • AP_FTYPE_NETWORK Фильтры этого типа запускаются последними. Они отвечают за чтение и запись данных из/в сети.
Большинство фильтров создаются исключительно как фильтры AP_FTYPE_CONTENT типа. После регистрации фильтра на сервере он может быть добавлен для обработки запросов. Это делается функцией ap_add_output_filter и обычно определяется с помощью директивы SetFilter в файле http.conf. Функция ap_add_output_filter принимает четыре аргумента:
ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c);
Первый аргумент - это имя, под которым фильтр был зарегистрирован в функции ap_register_output_filter. Аргумент ctx это произвольный указатель, который передается фильтру при каждом его вызове. Это бывает полезно, если одна функция имеет несколько вариантов исполнения. Последние два аргумента: request_rec и conn_rec, фильтр использует каждый раз при вызове. Если аргумент request_rec недоступен, то он должен быть равен NULL. Если request_rec равен NULL, тогда обязательно должен быть определен conn_rec. Они позволяют использовать одну цепочку фильтров для запроса и подзапросов без дополнительных обращений к Apache для определения какой запрос пришел от какого фильтра. Связывание запроса с фильтром происходит при добавлении фильтра в стек.
Эта статья только поверхностно рассматривает интерфейс фильтров, поэтому следующие две статьи будут посвящены углубленному рассмотрению этой темы. Написание фильтров является сложной задачей, но они являются мощным инструментом для расширения функциональности сервера.
Автор: Райн Блум (Ryan Bloom)
Перевод: Сипягин Максим
Оригинал документа (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
Опубликовано в: Разработка модулей Февраль 1, 2006

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

  1. СУПЕР!! СТАТЬЯ!!! Автору Респект!!
    _______________
    fatul.ru

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

  2. i kak eto uzat’?

    Комментарий от УПЯЧКА — Октябрь 16, 2008 @ 9:21 am

  3. a?

    Комментарий от УПЯЧКА — Октябрь 16, 2008 @ 9:21 am

  4. cho nikto ne znaet?

    Комментарий от УПЯЧКА — Октябрь 16, 2008 @ 9:22 am

  5. narooood

    Комментарий от УПЯЧКА — Октябрь 16, 2008 @ 9:23 am

  6. naroooodAAAAA

    Комментарий от УПЯЧКА — Октябрь 16, 2008 @ 9:23 am

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

You must be logged in to post a comment.

Работает на WordPress