Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

HTTP/1.1 Server from Scratch

Welcome to the HTTP/1.1 Server from Scratch course!

In this course, you will build an HTTP/1.1 server entirely from scratch, strictly following the official RFC specifications (RFC 9110 and RFC 9112).

By the end of this course, you will understand TCP sockets, request parsing, routing, chunked encoding, concurrent connection handling and much more!

Tip

If you’ve never looked under the hood of HTTP before, it might sound intimidating. But don’t worry! You’ll quickly discover that at its core, HTTP is surprisingly simple and elegant. It’s mostly just reading and writing formatted text over a socket. You’ve got this!

The Rules of the Game

You can write your server in any programming language you want. However, to get the most out of this course, you must follow one rule: No HTTP libraries.

You may use your language’s standard library for network sockets (e.g., net in Node.js, std::net in Rust, socket in Python) and concurrency. You may NOT use frameworks (like Express, Django, or Actix) or standard library HTTP modules (like Go’s net/http).

Prerequisites

To complete this course, you will need:

  • A programming language and runtime of your choice installed locally.
  • Docker installed and running (to run the evaluation suite).

How the Evaluation Suite Works

As you progress through the stages, you will test your code using our official test runner.

The setup works like this:

  1. You run your custom server locally, binding it to 0.0.0.0 on port 8080.
  2. You run our test suite via Docker.
  3. The Docker container fires a series of strict, edge-case HTTP requests at your server and evaluates the responses.

To run the entire evaluation suite against your server, open a separate terminal and run:

docker run \
  --rm \
  --add-host host.docker.internal:host-gateway \
  codeberg.org/level0/buildit/http-server:latest \
  --addr host.docker.internal:8080

What this command does:

  • --rm: Cleans up the container after the tests finish.
  • --add-host host.docker.internal:host-gateway: Ensures the container can communicate with your local machine’s localhost.
  • --addr: Tells the tester where to find your server.

Note

Instead of running the entire suite of tests every time, the runner uses an --until flag. This flag tells the tester to run all previous stages up to, and including, the stage you are currently working on. This ensures you haven’t broken any past functionality while building the new feature. At the end of every lesson, you will be provided with the exact docker run command required to evaluate that specific stage.

Course Syllabus

The course is broken down into a series of gradually advancing stages. You must complete them in order, as each stage builds upon the last.

Ready to begin? Head over to the first stage: Accept a Connection.