The craze of AI taking the jobs of developers really got me thinking about how i need to solidify my understanding of fundamental concepts so over the weekend i decided to build an HTTP server from scratch.
WHAT IS HTTP AND HOW DOES IT WORK
The HTTP(S) protocol is an application layer protocol which is stateless and is relies on TCP protocol for data transmission. When we say stateless we simply mean that a persistent connection between devices communicating is not maintained.The connection is broken after every data transfer.At the foundation of every HTTP server is a TCP server listening in for incoming connections and accepting. This implies that HTTP server is a wrapper around a TCP server. Based on this we can break down an HTTP server into its essential components and attempt building each of them and then finally putting them together
Main components of the HTTP server
- Base TCP server
- Request handler
- Request processor
- Response handler
Now lets pick each part and explore it.
Base TCP server:
The TCP server is a socket bound to a specific port and IP address, listening for incoming connections and deciding whether to accept or reject them.Most servers can handle concurrent connections and so I have to build the TCP server to handle connections concurrently.To handle this I took inspiration from the way databases handle connections concurrently with thread pools. For every accepted connection i spin up a worker thread to handle communications
Request Handler:
The request handler component i built extracts the necessary information from the request data and passes on to the processor component. For simplicity sake my focus was on serving static files. HTTP data is binary encoded and has three components; the request line,the request headers and the request body depending on the request method respectively as show below
example GET
GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
example POST
POST /api/login HTTP/1.1\r\n\
Host: localhost:8080\r\n\
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0\r\n\
Content-Type: application/json\r\n\
Content-Length: 44\r\n\
Accept: */*\r\n\
Connection: keep-alive\r\n\
\r\n\
{"username": "test_user", "password": "12345"}\r\n
My request handler parses the data and retrieves the request line. The request line is also parsed to retrieve the request method and the path. I then pass both the request method and and path to my request processor.
Request processor
My request processor locates the HTML file requested and encodes it in binary format. The encoded HTML file is then passed to the request handler
Response handler Finally the base TCP server closes the connection and the communication is ended.
My response handler receives the encoded HTML data and constructs the response in the standard HTTP response format
This is how a sample response will look like
HTTP/1.1 200 OK\r\n
Date: Sun, 09 Mar 2025 12:34:56 GMT\r\n
Content-Type: text/html\r\n
Content-Length: 125\r\n
Connection: keep-alive\r\n
Server: nginx/1.18.0\r\n
\r\n
Hello, World!
Access the code base for this project here