Simple-httpd


Описание программы и её возможностей

Simple-httpd - это небольшой http сервер для Колибри ОС, позволяющий размещать файлы, создавать динамические сайты и различные сетевые ресурсы.


Установка и настройка

Для упрощения установки в репозитории находится директория bin, которая представляет из себя сервер, файл конфигурации и некоторое количество демонстрационных модулей. Файл конфигурации в этой директории рассчитан на то, что сервер будет размещён в корне раздела "/usbhd0/3/".

Дальнейшая настройка содержимого директории зависит от значений в файле httpd.ini .

Примечание: Файл должен использовать кодировку UTF-8. Другие кодировки могут привести к неправильной работе сервера.

В файле конфигурации можно выделяются 3 основных раздела:

  1. [MAIN]

    Данный раздел содержит в себе базовые элементы конфигурации, такие как:

    Примечание: В качестве modules_dir могут использоватьбся только ASCII символы.

  2. [MODULES]

    Данный раздел может содержать множество элементов, представленных в виде:
    uri_path=file_name;cmdline , где

    Особенности работы: каждый модуль добавляется последовательно и поиск нужного модуля также производится последовательно. Из-за этой особенности нужно учитывать расположение uri в данной секции. Для того, чтобы uri модуля сравнивался с путём в запросе раньше всех остальных он должен находится в самом конце списка, чтобы

    Примечание: В качестве uri_path и cmdline может использоваться строка в UTF-8 с любыми символами, но путь к модулю всегда должен использовать только ASCII символы и не использовать символ ",". Кодировка cmdline не стандартизированна, но желательно использовать ASCII символы и проверять какую кодировку поддерживает модуль.

    Сервер имеет возможность установить модуль для некоторого диапазона uri путей, для этого используется символ "*", обозначающий неопределённое количество(включая ноль) любых символов. Например: При наличии записи /img/*=img_module.obj в секции модулей, сервер будет вызывать модуль для любых uri путей, имеющих в начале "/img/". Также для установки модуля на все возможные uri пути необходимо прописать соответствие модуля с путём "/*".

    Другие примеры: *.lua=lua_module.obj Любой путь, имеющий в конце ".lua".
    */.*=err401.obj Любой путь, имеющий в названии директорию, начинающуюся с символа ".".

  3. [TLS]

    ВНИМАНИЕ!!! TLS шифрование на данный момент не поддерживается сервером

    Данный раздел содержит необходимые данные для использования TLS сервером. Все поля обязательны для заполнения.

    Если сервер находит этот раздел, то он автоматически предполагает использоваться в режиме HTTPS сервера. Переход в этот режим будет использовать TLS для получения и отправки http данных, при этом порт подключения всё равно выбирается полем port в разделе [MAIN]. Если порт не задан, то в качестве стандартного порта будет выбран порт 443.

    Сервер одновременно может функционировать только в одном режиме, либо полностью использовать TLS, либо полностью не использовать. Это необходимо для предотвращения использования модулей, опирающихся на шифрование HTTPS протокола, в незащищённой среде передачи данных.


Документация на API модулей

Модули сервера позволяют обрабатывать запросы и отправлять отправлять ответ, в том числе и формируемый динамически. По своей структуре, модуль является обычной динамической библиотекой, экспортирующей 3 специальные функции:

  1. uint32_t __stdcall httpd_init(IMPORT_DATA* import, char* cmdline, char* uri_path)

    Функция для инициализации ресурса(uri_path), ассоциированного с модулем . В файле конфигурации для каждого ресурса можно добавить командную строку, передаваемую в эту функцию. Например test3=test_unit4.obj; -database="file.sqlite" Для большей совместимости рекомендуется обрабатывать эту командную строку в кодировке UTF-8.

    При успешной инициализации функция должна вернуть ненулевое значение, если же инициализация прошла неуспешно, то должен возвращаться ноль.

    Также для дальнейшей работы модуля предаётся указатель на таблицу экспортируемых сервером функций.

  2. void __stdcall httpd_serv(CONNECT_DATA* request_data, uint32_t pdata)

    Данная функция вызывается сервером при получении запроса на ресурс(uri_path) ассоциированным с модулем . Для обеспечения работы сервер передаёт в функцию уникальное значение, которое вернула функция "httpd_init" и указатель на структуру контекста запроса.

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

  3. void __stdcall httpd_close(uint32_t pdata)

    Функция вызывается сервером при завершении работы и необходима для правильности завершения обработки запросов в модулях и сохранения различных временных данных, если это необходимо. В функцию передаётся уникальное значение, возвращённое функцией "httpd_init".

    Завершение работы сервера производится вызовом экспортируемой функции "close_server".

    Алгоритм завершения работы модулей и самого сервера заключается в том, что сервер блокирует все новые запросы на подключение и вызывает функцию "httpd_close", для того чтобы модули завершили все открытые запросы и сохранили свои данные. После завершения всех модулей сервер полностью завершает свою работу.

Создание ответа на запрос

Любой запрос так или иначе требует ответа со стороны модуля. Этот ответ можно отправить используя экспортируемые ядром функции, позволяющие создать экземпляр класса RESPD и через него производить отправку ответа на запрос.

Далее будут перечислены некоторые функции для данного класса. Для полного ознакомления с функциями следует ознакомиться с примерами в директории example и файлом modules_api.inc в репозитории проекта.

В использовании функций добавления дополнительных заголовков и изменения версии есть особенность: строки должны существовать до момента деструктуризации объекта RESPD. Также модуль сам должен отслеживать и освобождать память под эти строки.

Обработка данных запроса

Работа с файлами

Примечание: Все пути на файл или директорию должны быть в кодировке UTF-8 или совместимой с ней ASCII. Строки должны использовать Null-турминатор. Кодировки UTF-16LE, cp866, cp1251 и тд нельзя использовать.

Управление сервером

void close_server();

Функция производит завершение работы всех модулей, и основного потока этого сервера. На время завершения работы модулей сервер блокирует все новые подключения, позволяя модулям завершить открытые соединения.

Дополнительные функции и возможности

char* __stdcall Get_MIME_Type(FILED* fd);

Функция производит анализ названия файла по его структуре FILED и возвращает MIME тип, соответствующий расширению файла. Данные о MIME типах берутся из встроенной таблицы соответствий либо из дополнительно загружаемого файла.


Дополнительные программы и средства

Генератор файла MIME типов

Хоть сервер и имеет встроенную таблицу сопоставления расширения файла и MIME типа, но этого недостаточно. По этой причине у сервера есть возможность загружать внешний файл с такой таблицей. Для генерации этого файла был создан макрос для fasm, позволяющий в удобном виде создать такой файл и указать все необходимые MIME типы.

Файл с расширенными MIME типами находится в репозитории в директории "utils" в этом же файле написан сам макрос. Последовательность передаваемых параметров в макрос следующая:

  1. Строка с MIME типом, который должен использоваться если не один другой тип не подходит
  2. Неопределённое количество последовательно идущих пар аргументов: сначала строка с расширением, например ".pdf", а после неё строка с MIME типом.

Модуль перенаправления запросов

При эксплуатации сервера может потребоваться возможность перенаправить запросы на какой-либо определённый файл(например на index.html) или модуль. Для данных целей к серверу был создан модуль "redirect.obj", позволяющий огранизовать перенаправление на определённые ресурсы как в пределах сервера, так и на внешние ресурсы. Для использования модуля необходимо задать модуль для всех необходимых uri путей и прописать для каждого такого uri командную строку, содержащую либо полный путь к ресурсу на этом сервере, либо полную uri ссылку. Пример использования:

/=redirect.obj, /docs/index.htm

перенаправление запросов на главную страницу сервера из корня.

Модуль блокировки доступа к файлам

При работе сервера, модули могут создавать различные "системные" файлы, например логи, к которым должен быть заблокирован доступ из запросов клиентов. Для этих целей к серверу был создан модуль "block_access.obj", позволяющий задать http код статуса и короткое сообщение в теле ответа сервера. Для использования необходимо связать модуль с uri путём и задать строку параметров: код статуса ответа и, через пробел, короткое сообщение. Пример использования:

*/.*=block_access.obj, 400 access error

Блокировка доступа к файлам и дерикториям начинающимся с символа "." .

Также можно не указывать текстовое сообщение, тогда сервер отправит только http статус. Если не указывать никаких параметров, то сервер будет по умолчанию отправлять код "403".


Известные баги и особенности

  1. Сетевой стек нестабилен и что-то может пойти не так.
  2. При отправки больших объёмов данных может быть утеря или изменение порядка пакетов
  3. Отсутствует поддержка частичных http запросов
  4. Сервер не рассчитан на большие нагрузки
  5. Отсутствует поддержка TLS