An HTTP server is a socket that speaks a text protocol. You build the accept loop and the parser against concrete specs, so each layer is solid before the next goes on top.
Over 36 short lessons you build a working HTTP/1.1 server from a bare TCP socket up. You start with an accept loop that echoes bytes, then write a request parser (request line, headers, Content-Length bodies), a response serializer (status lines, headers, auto Content-Length), a router, and a static-file handler with content types.
The last chapter makes it robust and concurrent: 400/404/405 error responses, HEAD, query parameters, one goroutine per connection, keep-alive, Connection: close, chunked request bodies, and an access log.
The end result is a real, teaching-grade server you run and hit with curl or a browser — it serves static files and dynamic routes over persistent connections. It deliberately stops short of TLS, HTTP/2, and the parts of RFC 9110/9112 (caching, ranges, cookies, content negotiation) a production server adds on top.
An HTTP server is a program that waits on a port for clients to connect. Today you open a listening socket and accept one connection, the raw foundation every later layer sits on.
Open a TCP listener on a port and accept a single incoming connection without error.
Before any HTTP exists, there must be a socket: an operating-system handle
for one end of a network connection. A server listens on an address, and each
time a client connects, Accept hands back a fresh connection you can read from
and write to.
Binding to port 0 asks the OS for any free port, which keeps tests from colliding on a fixed number. Read the real port back from the listener’s address so your test client knows where to dial. That is the whole handshake — bytes come next.
ln, err := net.Listen("tcp", "127.0.0.1:0") // :0 = OS picks a free port// ln.Addr() tells you which port you actually gotconn, err := ln.Accept() // blocks until a client connects_ = conn
The finished server runs and correctly handles routing, static files, persistent connections, HEAD, and chunked request bodies end to end, but still lacks production hardening like connection timeouts, request size limits, and graceful shutdown.
The current standard defining HTTP methods, headers, and status codes.
The wire-format spec for the request/response parsing this project implements directly.
A free, approachable guide to sockets - the layer HTTP sits on top of.
A broader tour of HTTP in practice: caching, proxies, and connection management beyond the core spec.