Урок 6. Свой веб-сервер
Этот сайт написан на «Сфере»: сервер, шаблоны, раздача файлов и загрузка установщиков. В уроке — минимальный сервер на библиотеке веб.код из стандартной библиотеки.
Минимальный сервер
подключить веб;
функция главная(): целое
результат из целого открыт = открыть_порт(8090);
если ( не открыт.успешно)
вывести(открыт.сообщение);
вернуть 1;
конец
целое32 слушающий = целое32(открыт.значение);
вывести("Сервер слушает на http://localhost:8090");
пока (да)
целое32 клиент = принять_подключение(слушающий, нулевой_указатель_сети(), нулевой_указатель_сети());
если (клиент не меньше целое32(0))
результат из Запрос запрос = прочитать_запрос(клиент);
если (запрос.успешно)
Запрос з = запрос.значение;
если (з.путь == "/")
ответ_html(клиент, 200, "<h1>Привет из Сферы!</h1><p><a href=\"/время\">Который час?</a></p>");
иначе если (з.путь == "/время")
ответ_html(клиент, 200, "<p>Секунд с 1970 года: " + целое_в_текст(юникс_время()) + "</p>");
иначе
ответ_html(клиент, 404, "<h1>Нет такой страницы</h1>");
конец
конец
закрыть_сокет(клиент);
конец
конец
вернуть 0;
конец
Запустите программу и откройте в браузере http://localhost:8090/. По адресу /время увидите число секунд, а по любому другому — страницу с кодом 404.
Как это устроено:
подключить веб;подключает библиотеку (она сама тянет за собойсетьипамять);открыть_портсоздаёт сокет и начинает слушать порт; вернуть она может ошибку, если порт занят;- в бесконечном цикле
принять_подключениеждёт клиента,прочитать_запросразбирает запрос в структуруЗапрос(поляметод,путь,параметры,заголовки,тело); ответ_html(клиент, код, тело)отправляет страницу; в конце соединение закрывается.
Что умеет веб.код
параметр(з.параметры, "имя")— значение из строки запроса?имя=значение;ответ_файлом_для(…)— отдача файлов с докачкой (Range),ETagи поддержкойHEAD; большие файлы идут кусками по 64 КБ;подставить(шаблон, имена, значения)— шаблоны с{{имя}};значение_cookie,заголовок_cookie,ответ_json,экранировать_html;принять_тело_в_файл— приём больших загрузок (через него сделана загрузка установщиков на этот сайт).
Многопоточность
Пример выше обслуживает по одному клиенту. Сайт запускает пул из 16 потоков, каждый из которых в цикле принимает подключения с общего сокета. Исходники — в репозитории в папке сайт/: сервер.код и сайт.код.
Безопасность
- Любой путь, пришедший из запроса, проверяйте функцией
путь_безопасендо обращения к файлам. - Весь текст пользователя, который вставляете в HTML, пропускайте через
экранировать_html. - HTTPS в язык пока не встроен: на сервере ставьте перед программой Caddy или nginx (см.
сайт/DEPLOY.md).
Упражнения
- Добавьте страницу
/привет?имя=…, которая здоровается с гостем (не забудьте экранировать имя). - Сделайте счётчик посещений в файле (подсказка:
дописать_в_файл_бинарноиразмер_файла).