- Написан сервер, который может выдавать статические страницы и выводить список файлов в каталоге (несколько подключений обслуживаются одновременно)
- Поддерживается возможность исполнения CGI скриптов, остановка "зависших" скриптов и (опционально) изоляция опасных скриптов при помощи chroot
- Сервер оформлен в виде юнита для systemd
- Сервер корректно обрабатывает ошибочные запросы (запрос несуществующего файла, попытка доступа к файлу без соответствующих прав доступа, запуск неработающего CGI-скрипта, некорректный GET-запрос и т.д.)
- Распознаются некоторые наиболее часто используемые типы файлов, такие как mp3 и pdf, что приводит к тому, что они открываются в браузере, а не скачиваются
- Настройки задаются в конфигурационном файле
- Поддержка POST-запросов
Веб-сервер - это программа, принимающая HTTP-запросы от клиентов (обычно веб-браузеров) и выдающая им HTTP-ответы (обычно вместе с HTML-страницей, изображением, файлом, медиа-потоком или другими данными). В настоящее время существует достаточно серверов, наиболее функциональные, известные и часто используемые из них - Apache, nginx и библиотеки для языков высокого уровня, реализующие почти всю необходимую функциональность (например, http.server для Python 3). Apache и является основным конкурентом (nginx не предназначен для запуска cgi-скриптов, его применение целесообразно прежде всего для статических веб-сайтов и как прокси-сервера перед динамическими сайтами). Их код сложен для понимания, и может содержать ошибки, в том числе опасные уязвимости. Актуальность данной работы состоит в написании простого сервера, не использующего сторонних библиотек (только libstdc++ и POSIX API), код которого можно быстро изучить и верифицировать. Современные веб-сервера поддерживают дополнительные возможности, такие как https, FastCGI (и другие протоколы взаимодействия с приложениями), POST (и другие виды запросов), авторизацию пользователей. При необходимости можно их добавить и к navajo. В целом, принцип работы всех серверов одинаков, но некоторые из них используют различные приёмы ускорения работы (например, очередь событий ядра epoll вместо создания отдельных процессов на каждое подключение при раздаче статических страниц, а также создания процессов заранее, во время простоя).
Написан сервер, отчёт, проведено сравнение производительности с Apache 2.
Сервер написан на C++ с использованием POSIX API для вызова функций, предоставляемых ОС. Использование C++ и RAII позволяет переложить рутинную работу с выделением и освобождением памяти на компилятор и избавиться от риска ошибок при работе с ней, а также использовать готовые алгоритмы и структуры данных, такие как хэш-таблицы. Для сборки используется CMake. Исходный код состоит из 6 файлов с исходным кодом и заголовков для них. Краткое описание:
- common.cpp - общезначимые константы и функции
- query_parser.cpp - функции для обработки запросов клиента
- answer_generator.cpp - функции ответа сервера на запросы
- config_reader.cpp - чтение конфигурационного файла
- url_encoder.cpp - процентное кодирование адресов
- main.cpp - код основной программы
- helper.cpp - код для выполнения chroot, компилируется в отдельный файл и выполняется от root (при помощи SUID бита)
-
Настройки по умолчанию можно изменить, поправив файлы sys/navajo.conf и sys/navajo.service
-
Компиляция
$ mkdir build
$ cd build
$ cmake ..
$ make
- Установка
# make install
- Запуск
# systemctl daemon-reload
# systemctl start navajo.service
Откройте в браузере страницу http://localhost:1200. Для демонстрации по умолчанию установлены несколько CGI-скриптов, можно их запустить и проверить работу сервера. variables выводит список переменных окружения, send/receive передают пользовательские данные, counter считает количество секунд после запуска. Скрипт pass запускает вечный цикл, и сервер должен прервать его выполнение через 1 секунду. Можно также положить в /var/www/navajo (или указанный в конфигурационном файле каталог) статические веб-страницы и медиаданные (pdf, mp3, png) и проверить, что сервер их распознал. Для включения режима изоляции потенциально опасных скриптов нужно указать параметр chroot в конфигурационном файле (пустое значение означает отключение этого режима), по указанному адресу должен быть каталог с установленными библиотеками для запуска скрипта, доступный для чтения, записи и выполнения пользователем navajo.
Как и планировалось, получился простой и быстрый сервер. По результатам тестирования производительности на рабочей машине автора navajo оказался на 19% быстрее Apache 2 (2.61 секунды на обработку 200 последовательных запросов против 3.22 секунд). Тестирование производилось на настройках Apache по умолчанию с двукратным запуском команды date и подсчётом разности времени до и после запуска (исходный код в test/performance, необходимо в нем задать номер порта и файл перед запуском).