Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Веб-программирование / Простой HTTP-сервер
Обслуживание множества запросов
Сервер с предыдущей страницы обработал один запрос и остановился.
Настоящий сервер продолжает работать, отвечая клиенту за клиентом.
Заверните шаги «принять — прочитать — ответить» в loop — и,
поскольку цикл разделяет переменные, объявленные вокруг него, между
запросами можно сохранять состояние. Здесь сервер считает своих
посетителей и сообщает каждому его номер:
my $listener = IO::Socket::INET.new(
:listen,
:localhost('127.0.0.1'),
:localport(8080),
);
my $customer = 0;
loop {
my $conn = $listener.accept;
$conn.recv;
$customer++;
# heredoc с qq:to даёт опрятный шаблон — переменная интерполируется прямо в нём
my $body = qq:to/END/;
Hello!
You are customer number $customer.
Thanks for visiting.
END
# сначала отправляем заголовок, затем тело — двумя отдельными записями
$conn.print("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
$conn.print($body);
$conn.close;
}.accept блокирует выполнение, пока
клиент не подключится, и затем возвращает новый сокет для этого
разговора. Поскольку $customer живёт вне цикла, она
переживает переход от запроса к запросу: первый посетитель — покупатель
1, второй — 2 и так далее. Цикл сам по себе
никогда не кончается, поэтому сервер работает, пока вы не остановите его
по Ctrl-C.
Стоит обратить внимание на две детали:
Ответ пишется в две части. Первый
.printотправляет HTTP-заголовок — строку состояния, тип содержимого и пустую строку, завершающую заголовки. Второй отправляет тело. HTTP безразлично, придёт это одной записью или несколькими, поэтому разделение позволяет держать неизменную протокольную обвязку отдельно от того, что действительно меняется.Тело берётся из шаблона.
qq:to/END/— это heredoc, строкаqq, которая тянется до строкиEND. Она занимает несколько строк и интерполирует$customerтак же, как любая строка в двойных кавычках, что делает её изящным средством шаблонизации для сборки ответа. (Это одна из конструкций кавычек, встречавшихся раньше в курсе.)
Подключитесь несколько раз, чтобы посмотреть, как растёт счётчик:
$ curl http://127.0.0.1:8080/
Hello!
You are customer number 1.
Thanks for visiting.
$ curl http://127.0.0.1:8080/
Hello!
You are customer number 2.
Thanks for visiting.Такая последовательная обработка запросов — простейший вид сервера. Промышленный сервер вдобавок обслуживал бы каждое соединение в отдельном потоке или промисе, чтобы медленный клиент не задерживал остальных, — но сердцем его остаётся именно этот цикл: принять, прочитать, ответить, повторить.
Навигация по курсу
← Ответ на запрос | Путь в верхнем регистре →
💪 Или перейдите сразу к упражнению
этого раздела.