Course of Raku / Functional, concurrent, reactive, and web programming / Web programming / A simple HTTP server
Serving many requests
The server on the previous page handled a single request and then
stopped. A real server keeps running, answering client after client.
Wrap the accept-read-respond steps in a loop — and because
the loop shares the variables declared around it, you can keep state
between requests. Here the server counts its customers and tells each
one their number:
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++;
# a qq:to heredoc makes a tidy template — the variable interpolates straight in
my $body = qq:to/END/;
Hello!
You are customer number $customer.
Thanks for visiting.
END
# send the header first, then the body, as two separate writes
$conn.print("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
$conn.print($body);
$conn.close;
}.accept blocks until a client connects,
then returns a fresh socket for that one conversation. Because
$customer lives outside the loop, it survives from one
request to the next: the first visitor is customer 1, the
second 2, and so on. The loop never ends on its own, so the
server stays up until you stop it with Ctrl-C.
Two details are worth noticing:
The response is written in two parts. The first
.printsends the HTTP header — the status line, the content type, and the blank line that ends the headers. The second sends the body. HTTP does not care whether these arrive in one write or several, so splitting them keeps the fixed protocol boilerplate apart from the part that actually changes.The body comes from a template.
qq:to/END/is a heredoc — aqqstring that runs to the lineEND. It spans several lines and interpolates$customerjust like any double-quoted string, which makes it a neat little templating tool for building a reply. (It is one of the quoting constructs from earlier in the course.)
Connect a few times to watch the counter climb:
$ 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.Handling requests one after another like this is the simplest kind of server. A production server would also serve each connection on its own thread or promise, so a slow client cannot hold up the others — but the heart of it is exactly this loop: accept, read, respond, repeat.
Course navigation
← Responding to a request | Upper-case the path →
💪 Or jump directly to the exercise to
this section.