Skip to content

Repository files navigation

WebServ

A from-scratch HTTP/1.1 server written in C++98, built as a team project at École 42.

No frameworks, no HTTP libraries — just sockets, epoll, and a hand-written request/response pipeline. Supports static file serving, CGI (PHP and Python), file uploads, directory listing, TLS, gzip compression, and multiple listening ports via a single non-blocking event loop.

What this demonstrates

  • Non-blocking I/O with a single epoll loop for all client socket traffic
  • A hand-written HTTP request parser (methods, headers, body, path normalization)
  • CGI execution via fork/execve, with two interpreters wired up (PHP and Python) to demonstrate the same mechanism working across languages
  • File uploads (multipart/form-data) and directory listing with delete support
  • TLS termination (OpenSSL) and gzip response compression (zlib) — both beyond the project's minimum scope
  • A configuration file that drives ports, error pages, and server limits

Stack

C++98 · epoll · OpenSSL · zlib · PHP-CGI · Python 3 · Docker

Getting started

Requires Docker (the server itself only builds on Linux — see Known Issues).

make -f Makefile.docker build
make -f Makefile.docker start

Inside the container:

make
./webserv conf/server.conf

The server listens on the ports declared in conf/server.conf (mapped to 8080, 4242, and others on the host via Makefile.docker). Open http://localhost:8080 in a browser.

Worth keeping that terminal visible: the server logs one line per request (method, path, referer) plus the first lines of each response, color-coded — green for success, yellow for warnings, red for errors, cyan marking the start of each request block.

Trying it out

Feature How to see it
Static site Navigate the site — Home, Form, Media, Team pages are all static HTML/CSS
CGI (PHP) login.html → posts to login.php. Credentials: demo / demo
CGI (Python) form.html → posts your name to process.py, returns a personalized greeting
File upload upload.html → upload an image (multipart/form-data), handled by upload.py
Directory listing + DELETE Same page — uploaded files appear with a working Delete button
A CGI failure (real 500) curl http://localhost:8080/cgi-bin/script_py/crash.py — a script that exits non-zero, showing a genuine CGI-failure 500 rather than a forced one
TLS curl -k https://localhost:4242 (self-signed cert, hence -k)
Multiple ports Same content is served on 8080–8083 and 4242

Every curl example above needs a User-Agent header containing Mozilla or curl — the server filters on it. All major browsers work out of the box (their User-Agent includes 'Mozilla' by convention); tools like Postman may need a custom User-Agent header.

Project structure

siteWebCss/            # static site + CGI scripts
├── cgi-bin/
│   ├── script_php/     # PHP CGI (login)
│   └── script_py/      # Python CGI (form processing, uploads)
└── ...                 # HTML/CSS/images

headers/                # .hpp files

srces/
├── ConfigParser/       # config file loading and validation
├── core/               # server loop, epoll, sockets, TLS
├── Response/           # response building, CGI execution
└── HttpRequest.cpp     # request parsing

Who built what

This was a two-person team project. Original split:

  • Sandra Kanna — configuration parser (ConfigParser/), response building and CGI execution (Response/), static site content (siteWebCss/)
  • Teammate — server core and event loop (core/), HTTP request parser
  • Both contributed to each other's areas along the way (config lookups, style/norm fixes)

Post-submission cleanup (this repo, solo effort): I ran a security and robustness audit across the full codebase — fixed a server-crashing bug, a CGI response-framing bug, hardcoded credentials, reorganized the CGI scripts. Full audit in commit history and KNOWN_ISSUES.md.

Known limitations

This implementation covers the core of an HTTP server — static serving, GET/POST/DELETE, CGI, uploads, TLS, multiple ports — but stops short of a few things a production server would need: per-route configuration (methods/redirects/roots are currently global or hardcoded), fully asynchronous CGI (a slow script blocks the event loop), and chunked transfer-encoding on incoming requests.

Full details, with file:line references and reasoning for what was fixed vs. documented, in KNOWN_ISSUES.md.

About

A from-scratch HTTP/1.1 server in C++98 — epoll, CGI (PHP/Python), TLS, and a security audit after the fact.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages