Структуры данных Apache. request_rec


Самой важной структурой данных в сервере Apache является request_rec. Она содержит все данные запроса, а также данные текущего соединения и конфигурацию сервера, на который пришел запрос.
Структура request_rec, которую мы рассмотрим, взята из исходников сервера Apache 2.2.2. request_rec, используемая в других версиях Apache 2, несколько отличается от этой, но большинство полей остались те же.

Теперь перейдем к делу. Сперва покажем полностью структуру, а ниже (по ссылкам из структуры) дадим детальное описание каждого поля.
Хорошее описание структуры request_rec есть в 12 главе книги "Администрирование Apache". Глава называется "Программирование сервера Apache" и содержит описание основных структур и API сервера. Эту книгу можно заказать в Озоне или в Болеро.

struct request_rec {
apr_pool_t *pool;
conn_rec *connection;
server_rec *server;
request_rec *next;
request_rec *prev;
request_rec *main;
char *the_request;
int assbackwards;
int proxyreq;
int header_only;
char *protocol;
int proto_num;
const char *hostname;
apr_time_t request_time;
const char *status_line;
int status;
const char *method;
int method_number;
apr_int64_t allowed;
apr_array_header_t *allowed_xmethods;
ap_method_list_t *allowed_methods;
apr_off_t sent_bodyct;
apr_off_t bytes_sent;
apr_time_t mtime;
int chunked;
const char *range;
apr_off_t clength;
apr_off_t remaining;
apr_off_t read_length;
int read_body;
int read_chunked;
unsigned expecting_100;
apr_table_t *headers_in;
apr_table_t *headers_out;
apr_table_t *err_headers_out;
apr_table_t *subprocess_env;
apr_table_t *notes;
const char *content_type;
const char *handler;
const char *content_encoding;
apr_array_header_t *content_languages;
char *vlist_validator;
char *user;
char *ap_auth_type;
int no_cache;
int no_local_copy;
char *unparsed_uri;
char *uri;
char *filename;
char *canonical_filename;
char *path_info;
char *args;
apr_finfo_t finfo;
apr_uri_t parsed_uri;
int used_path_info;
struct ap_conf_vector_t *per_dir_config;
struct ap_conf_vector_t *request_config;
const struct htaccess_result *htaccess;
struct ap_filter_t *output_filters;
struct ap_filter_t *input_filters;
struct ap_filter_t *proto_output_filters;
struct ap_filter_t *proto_input_filters;
int eos_sent;
};
apr_pool_t *pool; Пул запроса. Существует все время пока обрабатывается данный запрос. Используется для выделения памяти необходимой во время обработки запроса. Подробнее о пулах сервера и их использовании можно прочитать в этой статье.
conn_rec *connection; Структура, описывающая соединение, в контексте которого поступил запрос. Эта структура будет рассмотрена в следующей статье данной серии.
server_rec *server; Эта структура описывает виртуальный хост, к которому направлялся текущий запрос. server_rec также будет рассмотрена в отдельной статье.
request_rec *next; Указатель на перенаправляемый запрос в случае редиректа.
request_rec *prev; Указатель на предыдущий запрос в случае внутреннего редиректа. Внутренний редирект делается с помощью функции ap_internal_redirect_handler("/unique.html", r).
request_rec *main; Основной запрос, поступивший от клиента (в случае подзапросов и редиректа). Подробнее смотрите http_request.h.
char *the_request; Строка запроса. Например: "GET /resources/res.html HTTP/1.1". Это и нижние поля могут изменяться только в protocol.c.
int assbackwards; Флаг, показывающий использование протокола HTTP/0.9. При использовании HTTP/1.1 этот флаг равен 0.
int proxyreq; Используется в прокси модулях (например, mod_proxy) и определяет тип прокси запроса. Доступные значения:
  • PROXYREQ_NONE;
  • PROXYREQ_PROXY;
  • PROXYREQ_RESPONSE;
  • PROXYREQ_REVERSE.
Задается в обработчиках следующих хуков: post_read_request и translate_name.
int header_only; Флаг HEAD метода. В ответе возвращаются только HTTP заголовки, модули не должны отправлять контент на такой запрос.
char *protocol; Используемый протокол. Например, "HTTP/1.1"
int proto_num; Версия используемого протокола. Для проверки текущей версии используются два макроса: HTTP_VERSION_MAJOR и HTTP_VERSION_MINOR:
if ((HTTP_VERSION_MAJOR(r->proto_num) >= 1)
&& (HTTP_VERSION_MINOR(r->proto_num) >= 1)) {
/* Версия протокола либо 1.1, либо старше */
}
const char *hostname; Имя хоста, на который пришел запрос. Получено из заголовка Host или из r->the_request. Может не совпадать с именем хоста, обрабатывающего этот запрос.
apr_time_t request_time; Время поступления запроса на сервер. Для отображения request_time в виде "Tue May 23 17:31:32 2006" используйте функцию:
char rfctime[APR_RFC822_DATE_LEN];
apr_ctime(rfctime, r->request_time);
const char *status_line; Используется ядром сервера для генерации заголовка ответа.
int status; Код статуса HTTP. Устанавливается модулями уровня протокола.
const char *method; Метод запроса (например GET, HEAD, POST, и т.п.). Модуль может обработать это поле в случае нестандартного метода, не имеющего соответствующего номера.
int method_number; Код метода, например: M_GET, M_POST и т.п. В случае, если метод не известен ядру сервера, то значение method_number равно M_INVALID. В этом случае модулю необходимо использовать поле r->method.
apr_int64_t allowed; Битовая маска разрешенных методов. Обработчик должен убедиться, что метод запроса разрешен для обработки. Если нет, тогда модуль должен вернуть DECLINE. Перед отменой обработчик должен записать в r->allowed список методов, которые он обрабатывает. Эта маска используется для создания заголовка “Allow:” необходимого при запросах OPTIONS. Так как default_handler обрабатывает метод OPTIONS, все модули должны отвергать обработку OPTIONS. Метод TRACE всегда поддерживается, поэтому модулям не нужно устанавливать его явно. Так как default_handler всегда обрабатывает GET, модули, которые не реализуют метод GET, должны возвращать HTTP_METHOD_NOT_ALLOWED.
apr_array_header_t *allowed_xmethods; Массив разрешенных дополнительных (не поддерживаемых ядром сервера) методов. Для чтения методов можно использовать следующий код:
apr_array_header_t *array = r->allowed_xmethods;
for (i = 0; i < array->nelts; ++i){
const char *aray_item = ((const char **) array->elts)[i];
}
ap_method_list_t *allowed_methods; Массив разрешенных методов для этого запроса. Структура ap_method_list_t выглядит следующим образом:
struct ap_method_list_t {
/* Битовая маска разрешенных методов */
apr_int64_t method_mask;
/* Массив разрешенных методов */
apr_array_header_t *method_list;
};
apr_off_t sent_bodyct; Используется ядром сервера (protocol.c).
apr_off_t bytes_sent; После завершения обработки запроса это поле содержит количество байт тела отправленного ответа (без заголовков).
apr_time_t mtime; Время последнего изменения запрошенного ресурса. Для изменения используется функция ap_update_mtime(r, apr_time_now()).
int chunked; Флаг, показывающий будет ли тело ответа кодироваться блоками.
const char *range; Значение HTTP заголовка "Range:". Значение этого заголовка также доступно в headers_in.
apr_off_t clength; Настоящаяя длина ответа на данный запрос. Устанавливается с помощью функции ap_set_content_length(r, length).
apr_off_t remaining; Количество непрочитанных байт тела запроса. Обновляется ядром сервера каждый раз при чтении очередного блока тела запроса.
apr_off_t read_length; Противоположно предыдущей переменной, содержит количество уже прочитанных байт тела запроса.
int read_body; Метод чтения тела запроса. Возможные значения:
  1. REQUEST_NO_BODY. Если запрос содержит тело - вернуть 413 ошибку.
  2. REQUEST_CHUNKED_ERROR. Если запрос не содержит Content-Length - вернуть 411 ошибку.
  3. REQUEST_CHUNKED_DECHUNK. Если тело кодировано блоками - кодировка убирается.
int read_chunked; Кодировано ли блоками считываемое тело запроса?
unsigned expecting_100; Ожидает ли клиента ответа 100?
apr_table_t *headers_in; Заголовки запроса. headers_in содержит пары имя заголовка/значение всех заголовков запроса. Модули не должны изменять эти значения. Для доступа к этим значениям можно использовать следующий код:
// Обработчик заголовков
static int handle_table(void *data, const char *key, const char *val){
request_rec *r = (request_rec *)data;
return 1;
}
// Устанавливается обработчик заголовков
apr_table_do(handle_table, (void*)r, r->headers_in, NULL);
apr_table_t *headers_out; Заголовки ответа. Они НЕ используются при генерации ошибочного ответа. А при генерации "нормального" ответа эти заголовки объединяются с err_headers_out.
apr_table_t *err_headers_out; Эти заголовки используются для генерации всегда, даже в случае ошибочного ответа.
apr_table_t *subprocess_env; Название этого поля несколько неточно. Этот массив содержит переменные окружения доступные на следующих стадиях обработки запроса. Эти переменные актуальны только если необходимо создать дочерний процесс, например, для выполнения CGI скрипта. Однако эти значения также доступны, например, и для mod_include, в котором не создаются дочерние процессы.
apr_table_t *notes; Это поле не имеет четкой цели. Оно зарезервировано для обеспечения обмена данными между модулями (или обработчиками одного модуля) во время обработки запроса. Например, mod_speling использует notes для передачи списка возможных документов mod_negotiation.
const char *content_type; MIME тип тела ответа. Используется для генерации заголовка Content-Type. Например: application/octet-stream.
const char *handler; Имя генератора контента.
const char *content_encoding; Способ кодирования контента. Например: gzip, compress, deflate. Используется для генерации заголовка Content-Encoding.
apr_array_header_t *content_languages; Массив языков контента. Используется для генерации заголовка Content-Language.
char *vlist_validator; Так и не понял для чего это поле нужно :) . Кто знает - пишите мне на e-mail: info@apachedev.ru.
char *user; В случае, если проведена аутентификация, это поле содержит имя пользователя.
char *ap_auth_type; В случае, если проведена аутентификация, это поле содержит метод аутентификации.
int no_cache; Флаг запрета кеширования ответа на запрос.
int no_local_copy; Флаг отсутствия локальной копии запрошенного ресурса. Не дает серверу отправить заголовок "304 Not Modified".
char *unparsed_uri; Первоначальный URI без преобразований. Равен значению аргумента, переданного клиентом, например, методу GET. Будте внимательны, так как клиенты обычно передают только часть URI, содержащий только путь без имени хоста. Например, "/resources/generator.php?query=value"
char *uri; Часть URI, содержащая путь. Например, "/resources/generator.php".
char *filename; Имя файла на диске запрошенного ресурса.
char *canonical_filename; "Настоящее" имя файла запрошенного ресурса.
char *path_info; Содержит PATH_INFO, полученную из запроса.
char *args; Строка аргументов запроса (QUERY_ARGS).
apr_finfo_t finfo; Структура файла запрошенного ресурса. Описание структуры apr_finfo_t можно посмотреть тут.
apr_uri_t parsed_uri; Значение unparsed_uri, разобранное на следующие составляющие: схема, хост, путь, строка аргументов и т.п. Полное описание структуры apr_uri_t.
int used_path_info; Флаг использования или игнорирования path_info. Возможные значения:
  • AP_REQ_ACCEPT_PATH_INFO - Использовать path_info запроса.
  • AP_REQ_REJECT_PATH_INFO - Если в запросе есть path_info, нужно вернуть код 404.
  • AP_REQ_DEFAULT_PATH_INFO - Модуль сам решает, использовать ли path_info запроса.
struct ap_conf_vector_t *per_dir_config; Вектор конфигураций каталогов для запроса. Содержит директивы секций <Directory>, <Files> и <Location> для текущего запроса. Для получения конфигурации конкретного модуля используйте функцию ap_get_module_config(r->per_dir_config, &your_module_struct).
struct ap_conf_vector_t *request_config; Используется для передачи данных конфигурации подзапросам. Для доступа также используется функция ap_get_module_config.
const struct htaccess_result *htaccess; Связный список директив .htaccess для этого запроса.
struct ap_filter_t *output_filters; Список выходных фильтров, используемых для обработки запроса. Структура ap_filter_t выгдялит следующим образом:
struct ap_filter_t {
ap_filter_rec_t *frec;
void *ctx;
// next - указатель на следующий фильтр
ap_filter_t *next;
request_rec *r;
conn_rec *c;
};
А структуру ap_filter_rec_t, которая описывает фильтр, можно посмореть тут.
struct ap_filter_t *input_filters; Список входных фильтров, используемых для обработки ответа на запрос.
struct ap_filter_t *proto_output_filters; Список выходных фильтров уровня протокола, используемых для обработки запроса.
struct ap_filter_t *proto_input_filters; Список входных фильтров уровня протокола, используемых для обработки ответа на запрос.
int eos_sent; Флаг, определяющий отправлен ли EOS контейнер (EOS - флаг завершения потока).
Очень вероятно, что значения некоторых полей я описал не совсем корректно - к сожалению, не со всеми из них пришлось сталкиваться лично. Если у вас есть более точное описание, то присылайте его мне на info@apachedev.ru или оставляйте в комментариях.

Ссылки

  • Книга "Администрирование Apache" (Глава 12). Хорошее описание основных структур и API сервера. Озон Болеро

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
Опубликовано в: Архитектура Июнь 10, 2006

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

  1. такой обширной информации request_rec мне ещё не попадалось.

    Комментарий от Навигатор — Июль 9, 2008 @ 4:50 pm

  2. Да! Согласен! Сделано на совесть! Спасиба!!
    _________________
    health-kata.ru

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

  3. И ЧО ЭТО ТАКОЕ?

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

  4. ОЪЯСНИТИ

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

  5. ПЫЩЬ!111!!!

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

  6. ОЯЕБУ

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

  7. такой обширной информации request_rec мне ещё не попадалось.

    Комментарий от Леонард — Декабрь 22, 2008 @ 7:56 pm

  8. Нда, не с моими знаниями Апачи в этом разбиратся.

    Комментарий от fanki — Декабрь 24, 2008 @ 8:37 pm

  9. const struct htaccess_result *htaccess; Связный список директив .htaccess для этого запроса. не совсем сюда подходит

    Комментарий от Нина — Январь 4, 2009 @ 11:58 am

  10. Спасибо за полезную информацию!

    Комментарий от vitaliy_c9 — Январь 8, 2009 @ 12:30 pm

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

You must be logged in to post a comment.

Работает на WordPress