6.8 KiB
Simple HTTP Server
This project is a simple HTTP server that can serve static files. I had big plans for POST request support, a templating engine, and backend features, but just serving files turns out to be quite a lot of work, and I unfortunately ran out of time.
I was originally going to make a simple toy car dealership application for my final project, but I've wanted to write an HTTP server for a while, and since I had the time I decided to give it a shot. I'm proud that I was able to accomplish all this in just four days, especially since the basic file serving feature ballooned in complexity faster than I expected.
In hindsight there were a lot of decisions I would make differently around code architecture and organization, but I learned so, SO, much doing this project. It has definitely been worth the effort and mistakes even if it's a litte rough around the edges.
How to use
The project is designed to be very straightforward to run. It includes a Makefile and a Dockerfile. It should work on any linux system with build essentials. I have used Ubuntu for development. If you are unsure of your environment or running on a non-linux system, the running it in a docker container is the easiest way to go.
Deploying as a docker container
- Make sure docker is installed on your system.
- Clone the repository by running
git clone https://github.com/COS135-S2025/project-GShadow5.git - Run the container by running
docker compose upin the project root directory. (command may bedocker-compose upon some versions and platforms) - Navigate to http://localhost:8080/index.html in your browser.
- Navigate to other files found in the
publicdirectory, such as http://localhost:8080/image.png and http://localhost:8080/script.js
Building from source
- Clone the repository by running
git clone https://github.com/COS135-S2025/project-GShadow5.git - Build the project by running
makein the project root directory (where the Makefile is). - Run the server by running
./webserver.outin the project root directory. - Navigate to http://localhost:8080/index.html in your browser.
- Navigate to other files found in the
publicdirectory, such as http://localhost:8080/image.png and http://localhost:8080/script.js
Note on running on a remote server
If you run the project on a remote server, you'll need to forward port 8080, correctly configure your firewall, and use the external IP address of the server instead of localhost. The details of remote hosting are out of scope for these instructions.
Assignment checklist
- Use malloc LL or dynamic array - See the header_kv array in the http_request struct in http_stuff.h and http_stuff.c
- Use Makefile - I started out with the Makefile format from class, but that quickly became too cumbersome to work with, and I could not get incremental builds to work with the debug flag for some reason, so I upgraded to pattern matching and conditional compilation. It's still basic as make files go, but this is a small project.
- Assignments via pointers - This used to be EVERYWHERE in this project, but as the complexity grew I started using string library functions more. See lines 50 - 57 of request_handler.c for an example of pointer assignment. You can also look at the early commit history to see if all over the place.
- Loop through array with ptr increment/decrement - Used to be everywhere, but the only example left is line 16 of response_builder.c. Still meets the requirement though.
- No memory leaks - I have verified that the server does not leak memory by running Valgrind. There is a warning about a possible memory leak with
pthread_create, but that's normal for multithreaded applications. Since the thread detaches successfully, the memory that Valgrind is worried about gets collected by the OS when the thread terminates. - Reading and writing to files - Files are read every time a file is served; see response_build_static_file in response_builder.c. Files are written by the logger function in logging.c.
- Github - Everything is on github, and the commit history is EXTENSIVE.
- Switch statement - Used in response_build_static_file in response_builder.c and handle_request in request_handler.c.
- Something not taught in class - See below
Something[s] not taught in class
There are three major things not taught in class that are core to this project.
- The first is networking. It's an HTTP server and uses sockets to communicate. I've experimented with sockets before a few years ago before college, but this was the first time really digging into them.
- The second is multithreading. I am quite comfortable with multithreading because of some of my higher level classes, and I enjoy it a lot. Definitely not something typically taught in a 100 level class.
- Variadic arguments. I've never used variadic arguments before, but it was SUPER cool to find out I could make my own logging system. I've always wanted to do that, but most of the time I've been working in higher level languages that make it a nightmare. Variadic arguments are a awesome!
TODO List
- Get basic HTTP interaction working
- Get url parsing working
- Fix existing bugs in socket handling and TCP buffering
- Finish code to parse HTTP requests
- Update makefile to be more flexible
- Add enums for method types
- Add switch statement to handle different request types
- Add functions to handle each request type
- Finish code to build HTTP responses
- Get html file serving working
- Add flexible logging with variadic arguments
[ ] Make html page for uploading files[ ] Get POST requests working[ ] Implement file uploads (with restricted file types)[ ] Implement file indexing and serving a directory page[ ] Create basic templating engine for HTML working- Publish as a portfolio project
References
- HTTP status codes
- How I built a simple HTTP server from scratch using C: I used this to understand how to get started, but exapanded from it a lot.
- strtok reference: Didn't end up using strtok, but it was one of the approaches I tried for parsing the incoming requests.
- Variadic arguments references:
- I did not use any references for multithreading as I have used pthreads extensively for the last few semesters.
- Makefile reference: Used a bunch of this to understand how to write more complex makefiles.