Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

2006 г.

Модуль mod_dav. Архитектура модуля

Сипягин Максим, ApacheDev.ru

В предыдущей статье мы рассмотрели реализацию протокола WebDAV в сервере Apache. В этой статье, которая является последней в серии, мы рассмотрим устройство модуля mod_dav - центрального модуля поддержки протокола WebDAV в Apache. Также мы покажем как создавать собственные dav-провайдеры.

Введение

Как уже было сказано в предыдущих статьях [1, 2], модуль mod_dav является интерфейсным модулем, в котором происходит только обработка протокола WebDAV, а реализацию взаимодействия с хранилищем ресурсов, хранение свойств и т.п. модуль mod_dav делегирует сторонним модулям (back-end модулям или dav-провайдерами). В mod_dav такое взаимодействие реализовано в виде нескольких семейств хуков (сгруппированных по функциональности), обработчики которых должны быть реализованы dav-провайдерами.

Всего в mod_dav предоставлено семь групп хуков: обработка двух из них обязательна, а остальных - опционально. Сперва мы покажем общую схему, а затем опишем основные группы подробно.

Архитектура mod_dav

Рисунок. Архитектура mod_dav

На рисунке изображены все группы хуков, предоставляемых модулем mod_dav. Синим цветом выделены те группы хуков, для которых в dav-провайдере необходимы обработчики. Сейчас мы кратко рассмотрим каждую из этих групп, а ниже, уже более детально, изучим самые важные из них.
Название группы Описание
dav_hooks_repository Обязательная группа хуков. Объединяет хуки, отвечающие за взаимодействие с хранилищем ресурсов.
dav_hooks_propdb Обязательная группа хуков. В ней собраны хуки необходимые для работы со свойствами ресурсов (метаданными).
dav_hooks_liveprop Хуки для работы с Live-свойствами. Live-свойства предназначены для хранения значений, определяемых сервером, например: "getcontentlength" - длина тела ответа.
dav_hooks_locks Хуки для работы с блокировками ресурсов.
dav_hooks_vsn Версионность ресурсов.
dav_hooks_binding Связывание ресурсов.
dav_hooks_search Поиск ресурсов.

Теперь подробно рассмотрим три наиболее важные группы: dav_hooks_repository, dav_hooks_propdb и dav_hooks_locks.

mod_dav: Работа с хранилищем ресурсов

Для взаимодействия с хранилищем (репозитарием) ресурсов в mod_dav существует группа хуков dav_hooks_repository. Основное ее предназначение - это обработка входных и выходных потоков хранилища ресурсов. Обработчики этих хуков также обеспечивают выполнение основных файловых операций над ресурсами, например: копирование/перемещение ресурсов, создание коллекции, удаление ресурса и т.п.

Рассмотрим все хуки этой группы подробнее:

get_resource
Один из главных хуков данной группы. Обработчик хука get_resource связывает ресурс с URI запроса. Он должен возвращать структуру dav_resource, описывающую запрошенный ресурс. Структура dav_resource возвращается даже в случае, если запрошенный ресурс не существует.
get_parent_resource
Обработчик этого хука возвращает описатель (дескриптор) родительского ресурса для запрошенного URI. Если URI запроса указывает на корневую коллекцию, тогда возвращается NULL.
is_same_resource
Определяет, ссылаются ли два дескриптора на один и тот же ресурс.
is_parent_resource
Служит для определения, является ли один ресурс родительским для другого.
open_stream
Создает структуру потока - dav_stream, необходимую при заливке ресурса. Обработчик вызывается каждый раз, когда в хранилище добавляется новый ресурс.
close_stream
Закрывает открытый поток. Вызывается после того, как ресурс полностью залит.
write_stream
Вызывается циклически для блочной обработки данных закачиваемого ресурса.
seek_stream
Абсолютное смещение в потоке. Используется для поддержки заголовка Content-Range в методах GET/PUT.
set_headers
Вызывается перед отправкой ответа клиенту для установки заголовков. Обработчик хука deliver не вызывается, если используется метод HEAD.
deliver
Одни из главных хуков группы. Используется для отправки ресурса в заданный фильтр. Используется как для ресурсов, так и для коллекций.
create_collection
Создает коллекцию. В случае, если коллекция создана успешно, обработчик должен вернуть NULL.
copy_resource
Хук копирования ресурса или коллекции. Свойства ресурсов также копируются.
move_resource
Перенос ресурса.
remove_resource
Хук удаления ресурса или коллекции. При удалении ресурса также удаляются и его свойства.
walk
Хук обхода иерархии коллекций и ресурсов. Используется, когда запрос поступил на коллекцию и глубина обхода больше 0 (т.е. необходимо обработать вложенные объекты).
getetag
Получить ETag для ресурса.

mod_dav: Работа со свойствами

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

open
Получаем дескриптор хранилища свойств.
close
Закрываем открытое хранилище свойств.
define_namespaces
Определение внутренних пространств имен для свойств.
output_value
Получение значения определенного свойства для указанного ресурса.
map_namespaces
Отображение глобальных пространств имен на пространства имен dav-провайдера.
store
Сохранить значение свойства для указанного имени.
remove
Удалить свойство.
exists
Проверяет, существует ли такое свойство.
first_name
Возвращает имя первого свойства ресурса.
next_name
Возвращает имя следующего свойства.
get_rollback
apply_rollback
Поддержка механизма отката изменений. Провайдером задается структура dav_deadprop_rollback, в которой хранятся старые имена и значения свойств.

mod_dav: Блокировки

Последняя группа, которую мы рассмотрим, отвечает за функционирование механизма блокировок. Она не является обязательной, но необходима для реализации методов WebDAV: Lock и Unlock.

get_supportedlock
Возвращает значение свойства supportedlock для ресурса.
parse_locktoken
Парсит поступивший токен блокировки. Тут мы создаем и возвращаем структуру dav_locktoken.
format_locktoken
Преобразуем структуру dav_locktoken в строку URI.
compare_locktoken
Сравниваем два токена блокировок.
open_lockdb
Открывает и подготавливает хранилище блокировок. Dav-провайдер может воспользоваться значением директивы DAVLockDB для размещения своего хранилища (значение можно получить с помощью функции dav_get_lockdb_path()).
close_lockdb
Хук завершения работы с блокировками.
remove_locknull_state
Выводим ресурс из состояния lock-null.
create_lock
Создаем блокировку для ресурса. В обработчике этого хука должен быть создан токен новой блокировки.
get_locks
Получить все блокировки указанного ресурса.
find_lock
Найти блокировку ресурса по заданному токену.
has_locks
Хук проверки ресурса на наличие блокировок. Должна возвращать TRUE, даже если у ресурса есть только блокировки с истекшим сроком жизни (time-out).
append_locks
Добавить блокировки ресурсу.
remove_lock
Удалить блокировку с заданным токеном.
refresh_locks
Обновить блокировки у ресурса. Список токенов задает блокировки, которые необходимо обновить. Также в качестве аргумента передается структура time_t, описывающая текущее время.
lookup_resource
Найти ресурс, связанный с указанным токеном блокировки.

Теперь, после рассмотрения основных групп хуков модуля mod_dav, перейдем к практике. И посмотрим на код модуля-провайдера. Я не буду мешать код с текстом, поэтому все пояснения оформлены в виде комментариев к коду.

Структура dav - провайдера

Совет: Нижеизложенный код изучать лучше с конца.

// структура модуля для хранения директив
typedef struct {
    const char *test_dav_directive;
}test_dav_server_conf;
// Обработчик хука post_config
static int test_dav_post_config(apr_pool_t *p, apr_pool_t *plog,
                                apr_pool_t *ptemp, server_rec *s) {
    // Выполняем действия, необходимые для инициализации
    // Данный обработчик вызывается после загрузки модуля и
    // после обработки конфигурации
    // (Примечание: Данный обработчик выполняется при загрузке дважды.
    // Способ обойти такое поведение читайте в статье
    // «Проблемы при создании модуля»)
	return OK;
}
// Создать структуру конфигурации модуля
static void *create_server_config(apr_pool_t *p, server_rec *s){
    test_dav_server_conf *conf = NULL;
    conf = (test_dav_server_conf*)apr_palloc(p, sizeof(*conf));
    return (void*)conf;
}
// Обработчик директивы
static const char *test_dav_cmd(cmd_parms *cmd, void *config,
                                const char *arg1){
    test_dav_server_conf *conf;
    // Получить указатель на структуру конфигурации модуля
    conf = ap_get_module_config(cmd->server->module_config, &test_dav_provider_module);
    // Сохранить значение директивы
    conf->test_dav_directive = apr_pstrdup(cmd->pool, arg1);
    return NULL;
}
// Директивы модуля
static const command_rec test_dav_cmds[] = {
    // Декларация директивы и ее обработчика
    AP_INIT_TAKE1("tes_dav_directive", test_dav_cmd, NULL, ACCESS_CONF|RSRC_CONF,
                "Тестовая директива с одним аргументом"),
    {NULL}
};
// Структура DAV провайдера
static dav_provider test_dav_provider =
{
    &test_dav_hooks_repos,      // Работа с хранилищем
    &test_dav_hooks_propdb,     // Работа со свойствами
    &test_dav_hooks_locks,      // Блокировка
    NULL,                       // Версионность
    NULL,                       // Связывание
    NULL                        // Поиск
};
// Регистрация обработчиков хуков
static void register_hooks(apr_pool_t *pconf){
    ap_hook_post_config(test_dav_post_config, NULL, NULL, APR_HOOK_MIDDLE);
    // Регистрация DAV провайдера
    dav_register_provider(pconf, "test_dav_provider", &test_dav_provider);
}
// Главная структура модуля Apache
module AP_MODULE_DECLARE_DATA test_dav_provider_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    create_server_config, // создание конфигурации модуля
    NULL,
    test_dav_cmds,	// список директив модуля
    register_hooks, // регистрация обработчиков
};

Данный код, а также код обработчиков test_dav_hooks_repos, test_dav_hooks_propdb и test_dav_hooks_locks можно скачать в виде архива.

Послесловие

Это последняя статья из серии про модуль mod_dav. Надеюсь, что она стала вам полезной и сняла часть вопросов, касающихся реализации WebDAV в сервере. Если у вас остались вопросы, то присылайте их мне на info@apachedev.ru. До встречи.

VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

Новости мира IT:

Архив новостей

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 7861149
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...