This is a solution to "Build Your Own HTTP server" Challenge on codecrafters.io.
They have fun challenges to practice programming and software engineering.
As a solution to the HTTP server challenge, I tried to make a small version of the net/http package of the go standard library.
Along the way, I learned the following topics:
- HTTP protocol in depth
- Go language features
- Interfaces
- goroutines
- synchronization
- File handling
- Web technology
- The request-response flow
- HTTP routes and route Multiplexer
It has 4 routes by default.
GET /
Hello There!
GET /user-agent
echoes back whatever is in user-agent headers
GET /echo/message
echoes back the message part
GET /files/filename
Gets the content of the file
POST /files/filename
Writes the post data to the filename
USAGE
./your_server.sh --directory <path/to/a/directory>
--directory: Directory path for files/<filename> route
Output
INFO[0000] Registering route /
INFO[0000] Registering route /user-agent
INFO[0000] Registering route /echo/<msg>
INFO[0000] Registering route /files/<filename>
INFO[0000] Serving at: 0.0.0.0:4221
The server registers the routes and listens at 0.0.0.0:4221
One of the most challenging parts for me was to continue reading on the port with a fixed-sized buffer when further data is expected. It is especially relevant for POST methods that may include a body of size Content-Size
as specified in the header. A fixed buffer may not be enough to accumulate the whole data. I used go routine to keep reading the data from the socket and append to the buffer until there is no data left or the connection was closed.
Another was a custom multiplexer for routes. Currently, the app accepts non-consecutive path parameters. For example /books/<id>
, /countries/<id>/nepal/<state>
are accepted but not /vehicles/<car>/<brand>
. I have used a word-based Trie for the multiplexing algorithm(character-based would have been more efficient🤔)