Skip to content

Biny17/webserv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

239 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌐 WebServ

A lightweight HTTP/1.1 web server written in C++98, built from scratch with no external dependencies.

42 School project β€” reimplementing core web server behavior from the ground up.


πŸ“‹ Table of Contents


Overview

WebServ is a fully functional HTTP/1.1 server implemented in C++. It handles real browser requests, serves static content, and executes CGI scripts β€” all driven by a custom configuration file inspired by NGINX syntax.

Internally, it uses epoll (Linux) for I/O multiplexing, allowing the server to monitor multiple client connections simultaneously within a single thread β€” no blocking, no busy-waiting. Each event (new connection, incoming data, response ready) is dispatched through a non-blocking event loop, keeping the server responsive under concurrent load.

CGI processes are spawned via fork + execve, with communication handled through pipes (stdin/stdout). A timeout mechanism ensures hanging scripts don't stall the server indefinitely.


Features

  • βœ… HTTP/1.1 β€” GET, POST, DELETE methods
  • πŸ“ Static file serving β€” HTML, CSS, JS, images, and more
  • πŸ›£οΈ Static routes β€” define URL-to-directory mappings via config
  • βš™οΈ CGI support β€” execute scripts (Python, PHP, etc.) on the server side
  • πŸ“„ Config file β€” flexible server configuration (ports, hosts, routes, error pages...)
  • 🚫 Custom error pages β€” 404, 403, 500 and more
  • πŸ” Redirections β€” HTTP 301/302 support
  • πŸ“¦ No external dependencies β€” pure C++98 stdlib only

Architecture

Non-blocking I/O with epoll

WebServ uses epoll (Linux) to handle multiple concurrent connections within a single thread. All sockets β€” server and clients β€” are set to non-blocking mode. The event loop monitors file descriptors and reacts only when data is actually ready, avoiding busy-waiting entirely.

epoll_wait() ──► event on fd
                    β”œβ”€β”€ server socket  β†’  accept() new client
                    β”œβ”€β”€ client socket  β†’  read request / send response
                    └── CGI pipe       β†’  read script output

This means the server never blocks on a single slow client, and can handle many simultaneous connections efficiently without threading.

Request lifecycle

accept()  β†’  parse HTTP request  β†’  match location block
          β†’  serve file / redirect / exec CGI
          β†’  build HTTP response  β†’  send()  β†’  close or keep-alive

CGI execution

CGI scripts are launched via fork() + execve(). The server communicates with the child process through a pipe: request body is written to stdin, and the script's stdout is read back as the response body. A timeout mechanism kills stalled CGI processes to prevent the server from hanging.


Getting Started

Requirements

  • clang++
  • make
  • Unix-based OS (Linux / macOS)

Build

git clone https://github.com/Biny17/webserv.git
cd webserv
make

Run

./webserv [config_file]

If no config file is provided, the server uses a default configuration.

./webserv config/server.conf

Then open your browser at http://localhost:8080.


Configuration

The config file follows an NGINX-inspired syntax. Here's a minimal example:

server {
    listen       8080;
    server_name  localhost;

    root         ./www;
    index        index.html;

    error_page   404 /errors/404.html;

    location / {
        allow_methods  GET POST;
        autoindex      on;
    }

    location /upload {
        allow_methods  POST;
        root           ./www/uploads;
    }
}

Supported directives

Directive Description
listen Port to listen on
server_name Virtual host name
root Root directory for file serving
index Default file to serve
error_page Custom error pages
allow_methods Allowed HTTP methods per location
autoindex Enable/disable directory listing
return HTTP redirect
cgi_extension Allowed CGI extensions
client_max_body_size Max request body size

CGI Support

WebServ can execute CGI scripts based on file extension.

location /cgi-bin {
    allow_methods  GET POST;
    cgi_extension  .py .sh .rb;
}

CGI scripts receive request data via environment variables and stdin, and return their response through stdout β€” following the CGI/1.1 standard.


Project Structure

webserv/
β”œβ”€β”€ cgi-bin/                # CGI scripts
β”œβ”€β”€ config/                 # Configuration files
β”œβ”€β”€ headers/                # Header files (.hpp)
β”œβ”€β”€ srcs/                   # Source files (.cpp)
β”‚   β”œβ”€β”€ cgi/                # CGI execution (fork, pipe, env)
β”‚   β”œβ”€β”€ classes/            # Core classes (Server, Client, Request, Response...)
β”‚   β”œβ”€β”€ conf/               # Config file parser
β”‚   β”œβ”€β”€ handle_request/     # GET / DELETE response logic
β”‚   β”œβ”€β”€ network/            # Epoll event loop, client handling
β”‚   └── utils/              # Helpers (autoindex, encoding, path...)
β”œβ”€β”€ www/                    # Default web root
β”œβ”€β”€ Makefile
└── README.md

Authors

Name GitHub
Anicet Gruet @Anicet78
Tom Pinton @Snak00s
Tristan Biny @Biny17

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors