This project has been created as part of the 42 curriculum by lifan, yren, cwang
The goal of the project is to build a fully functional HTTP/1.0 server from scratch, without using external frameworks, and to understand how web servers work at a low level. The server is designed as a non-blocking, multiplexed web server, capable of handling multiple client connections efficiently using event-driven I/O.
- Event-driven architecture using a virtual IEventHandler interface The server is built around an event-driven design, where all file descriptors (sockets, client connections, CGI pipes, etc.) are managed through a common abstract interface IEventHandler. This allows polymorphic handling of different types of events (read, write, error) and improves modularity, extensibility, and maintainability of the codebase.
- Full integration of CGI I/O through epoll Communication with CGI scripts (both input and output streams) is entirely handled through the epoll event loop. This ensures non-blocking behavior for CGI execution, allowing the server to handle multiple clients and CGI processes concurrently without performance bottlenecks.
- Non-blocking, asynchronous I/O model All sockets and file descriptors are configured in non-blocking mode and monitored via epoll. This enables efficient handling of a large number of simultaneous connections with minimal resource usage, following modern high-performance server design principles.
- HTTP/1.0 compliant implementation The server conforms to the HTTP/1.0 specification, supporting core features such as: Request parsing (methods, headers, body) Response generation with proper status codes Connection handling (including Connection: close) Basic error management
The project is divided into three main modules, each developed by one team member.
This module is responsible for the entire network infrastructure of the server.
It creates and manages all sockets, and handles:
bind,listen,accept,Multi-connection event monitoring using epoll
It reads raw byte streams from clients and forwards complete HTTP request strings to the HTTP module.
After the response is generated, this module sends the formatted HTTP response back to the client.
This part focuses on: Connection state management;Buffers;Connection lifecycle
+----------------------+
| main |
+----------+-----------+
|
v
+----------------------+
| Webserv |
| (init + config load) |
+----------+-----------+
|
v
+----------------------+
| Epoll Manager |
| (Event Loop) |
+----------+-----------+
|
-----------------------------------------------------
| | |
v v v
+----------------+ +----------------+ +------------------+
| Listen Socket | | Client Socket | | CGI Pipes |
| Handler | | Handler | | Handler |
+--------+-------+ +--------+-------+ +--------+---------+
| | |
| accept() | read/write | pipe I/O
v v v
+----------------+ +--------------------------+
| New Client |->| Request Buffer |
| Connection | | (accumulate raw data) |
+----------------+ +------------+-------------+
|
v
+----------------------+
| HTTP Module |
| (parse request) |
+----------+-----------+
|
v
+----------------------+
| Routing / Config |
| (decide request type)|
+----------+-----------+
|
-------------------+-------------------
| |
v v
+----------------------+ +----------------------+
| Static Methods | | CGI |
| (GET/POST/etc.) | | (exec + pipes) |
+----------+-----------+ +----------+-----------+
| |
v v
+----------------------+ +----------------------+
| Build HTTP Response | | Build HTTP Response |
| (headers + body) | | (from CGI output) |
+----------+-----------+ +----------+-----------+
| |
---------------+------------------------
v
+----------------------+
| Write Buffer |
+----------+-----------+
|
v
send() to client
- Additional Event Loop Responsibilities: Timeout management (clients & CGI) Connection lifecycle handling FD registration/removal in epoll
This module handles everything related to the HTTP protocol.
It parses raw request strings into a structured HttpRequest object, including: Method,Path,Headers,Body
It performs protocol-level validation, such as: Valid HTTP methods;HTTP version checking;Header format validation;Keep-alive management
After the request is processed, this module builds a complete HTTP response string based on: Status code,Headers,Body
This module is responsible for the overall behavior and decision-making of the server.
It Reads and parses the configuration file
Builds internal representations of server and location blocks
Based on the HttpRequest, it Selects the appropriate configuration block
Decides whether the request should be handled as: Static file serving;CGI execution;File upload
It outputs a structured HttpResponseData object, which is passed to the HTTP module to generate the final response.
Simple explanation for CGI: CGI (Common Gateway Interface) is a mechanism that allows a web server to execute an external program (such as a Python or PHP script).
The server passes request information to the program through environment variables, and can also send the request body via stdin.
It connects pipes: stdin → to send request body to CGI stdout → to receive CGI output Then it runs the script using execve() The CGI program: reads input from stdin reads metadata from environment variables writes the result to stdout The server reads that output and sends it back as the HTTP response
[HTTP body]
|
v
webserv (parent process)
|
| write()
v
inPipe[1] ---> inPipe[0]
|
| read()
v
CGI stdin
|
v
execute CGI program
|
v
CGI stdout
|
| write()
v
outPipe[1] ---> outPipe[0]
|
| read()
v
webserv (parent process)
|
v
[HTTP response]
- Compile the project:
make- Run the server with a configuration file:
./webserv config/conf.conf- Verify the server is running on a port:
lsof -i :8080- Open Open in a browser:http://localhost:8080 Or use curl (in another terminal)
curl http://localhost:8080/- Multiple Servers and Ports Access different ports:
curl http://localhost:8080/
curl http://localhost:8081/- Use different hostnames:
curl --resolve demo_localhost:8081:127.0.0.1 http://demo_localhost:8081/
curl --resolve localhost:8080:127.0.0.1 http://localhost:8080/- Error Pages Request a nonexistent page to test custom error pages:
curl -v http://localhost:8080/nonexistent_page- Exceed the client body limit:
head -c 11000000 /dev/zero | curl -X POST \
-H "Content-Type: text/plain" \
--data-binary @- http://localhost:8080/upload- Within the limit:
curl -X POST -H "Content-Type: text/plain" \
--data "short" http://localhost:8080/- Access different routes:
curl http://localhost:8080/images/
curl http://localhost:8080/static/
curl http://localhost:8080/upload/- Access a file inside a route:
curl http://localhost:8080/storage/little.txt- Nonexistent route returns 404:
curl http://localhost:8080/uploads/- Default file in directory:
curl http://localhost:8080/
curl http://localhost:8080/subdir/- GET allowed:
curl -X GET http://localhost:8080/protected/- Disallowed methods return 405:
curl -X POST http://localhost:8080/protected/
curl -X DELETE http://localhost:8080/protected/- Upload and Download Files
- Upload a file:
curl -X POST --data "hello world" \
http://localhost:8080/upload/testfile.txt- Download a file:
curl http://localhost:8080/storage/testfile.txt- Run a CGI script:
curl http://localhost:8080/cgi-bin/cgi_python.py- POST to CGI:
curl -X POST -d "username=abc&pwd=123" \
http://localhost:8080/cgi-bin/cgi_python.py- GET with query parameters:
curl "http://localhost:8080/cgi-bin/cgi_python.py?name=alice&age=18"- Run siege stress test:
siege -b -c 10 -t 30S http://localhost:8080/index.html- Monitor memory usage:
watch -n 1 "ps -o pid,rss,vsz -p <PID>"- Stop the server:
pkill webserv```
or use
```bash
lsof -i :8080to show PID and kill PID
-
HTTP, Web
https://developer.mozilla.org/fr/docs/Web/HTTP https://developer.mozilla.org/fr/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_web_server https://blog.o2switch.fr/comprendre-les-pages-derreurs-http-sur-le-web/ https://developer.mozilla.org/fr/docs/Web/HTML -
Tutoriels
https://medium.com/@md.abir1203/nuts-and-bolts-of-a-http-webserver-94549992f660 https://m4nnb3ll.medium.com/webserv-building-a-non-blocking-web-server-in-c-98-a-42-project-04c7365e4ec7 -
Non blocking
https://noobtomaster.com/rest-with-spring-boot/non-blocking-i-o-with-spring-webflux/ https://medium.com/@m-ibrahim.research/mastering-epoll-the-engine-behind-high-performance-linux-networking-85a15e6bde90 https://cs4157.github.io/www/2024-9/lect/10-adv-io.html -
Prototypes
https://www.man7.org/linux/man-pages/man3/sockaddr.3type.html https://www.man7.org/linux/man-pages/man2/bind.2.html https://www.man7.org/linux/man-pages/man2/listen.2.html https://www.man7.org/linux/man-pages/man2/accept.2.html
- Documentation & Writing Improved clarity and structure of this README Helped rephrase and refine technical explanations Assisted with translation (e.g., French ↔ English)
- Debugging Support Provided guidance when investigating bugs Suggested possible causes and debugging strategies Helped analyze unexpected behaviors in the code
- Conceptual Understanding Answered questions about key concepts such as: HTTP protocol Non-blocking I/O epoll/event loops CGI execution model