This project has been created as part of the 42 curriculum by Ayman Elasefar (ayelasef), Abderrahmane Habibi Ihlane (ahabibi-), Ayoub Laaoufi (aylaaouf).
Webserv is a fully functional HTTP/1.1 web server written from scratch in C++98, inspired by the architecture and configuration style of nginx. It is a core milestone of the 42 school curriculum, designed to give students a deep understanding of how web servers work under the hood.
The server handles real-world HTTP communication in a single-threaded, non-blocking event loop powered by poll(). It supports multiple virtual hosts, location-based routing, CGI script execution, file uploads, static file serving, and persistent connections — all without relying on threads or blocking I/O on the main loop.
- Non-blocking I/O via
poll()— single event loop, no threads, no blocking syscalls - HTTP/1.1 compliance: persistent connections (
keep-alive), correct status codes, headers - Multiple virtual servers with independent
listen,server_name,host, anderror_pagedirectives - Location blocks with per-route method restrictions,
autoindex,index, andreturn(redirect) - CGI support (Python) — fully asynchronous, pipe fds registered in the poll loop
- CGI timeout — unresponsive child processes are killed and reaped after a timeout; a
504 Gateway Timeoutis returned - File uploads via
POSTwithclient_max_body_sizeenforcement - Static file serving with auto-generated directory listings (
autoindex on) - HTTP Range requests —
206 Partial Contentfor video streaming - Session & cookie management — cookie-based session tracking with eviction of idle sessions
- Custom error pages per server block
- Graceful shutdown with
SIGINThandling
- A C++98-compatible compiler (
c++org++) - GNU
make - A POSIX-compliant OS (Linux or macOS)
git clone https://github.com/aelasefa/Webserv.git
cd Webserv
makeThis produces a webserv binary in the project root. The build uses -Wall -Wextra -Werror flags throughout.
./webserv [config_file]If no config file is provided, the server falls back to conf/Default.conf.
Example:
./webserv conf/Default.confThen open your browser at http://localhost:8080/ or test with curl:
curl -v --http1.1 http://localhost:8080/The configuration syntax follows an nginx-inspired block structure:
server {
listen 8080;
server_name localhost;
host 127.0.0.1;
root www/;
client_max_body_size 1000000;
index index.html;
error_page 404 error_pages/404.html;
location / {
allow_methods GET POST;
autoindex off;
}
location /uploads {
allow_methods GET POST DELETE;
autoindex on;
upload_store www/uploads/;
}
location /cgi-bin {
allow_methods GET POST;
cgi_extension .py;
}
}Supported directives:
| Directive | Scope | Description |
|---|---|---|
listen |
server | Port to bind |
server_name |
server | Virtual host name |
host |
server | IP address to bind |
root |
server / location | Document root |
index |
server / location | Default index file |
client_max_body_size |
server | Maximum request body size (bytes) |
error_page |
server | Custom error page per status code |
allow_methods |
location | Allowed HTTP methods (GET, POST, DELETE) |
autoindex |
location | Directory listing (on / off) |
upload_store |
location | Target storage path for uploaded files |
cgi_extension |
location | File extensions handled by CGI |
return |
location | HTTP redirect to another path |
# Install siege
apt-get install siege # Debian/Ubuntu
brew install siege # macOS
# Run a load test (255 concurrent users for 30 seconds)
siege -c255 -t30S http://localhost:8080/Target: Target 100% availability with no leaks or hung connections.
make clean # remove object files
make fclean # remove object files and binary
make re # full rebuild- RFC 7230 — HTTP/1.1: Message Syntax and Routing
- RFC 7231 — HTTP/1.1: Semantics and Content
- RFC 7233 — HTTP/1.1: Range Requests
- Beej's Guide to Network Programming
- MDN Web Docs — HTTP
- nginx documentation
- RFC 6265 — cookies and HTTP State Management
man poll,man socket,man accept,man recv,man sendman fork,man execve,man waitpid,man pipe- The C10K Problem — Dan Kegel
- IBM — Non-blocking I/O and select()