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🤔)