Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webserv

webserv is a fully functional HTTP/1.1 server written in C++98, built from scratch without any external libraries.

Features

  • Multiple virtual servers — host multiple servers on different IP/port pairs from a single config file
  • HTTP methods — GET, POST, DELETE
  • CGI support — execute .py, .sh scripts via configurable CGI path
  • File uploads — configurable upload directory per location
  • Autoindex — optional directory listing when no index file is found
  • Multiple index support — serves the first existing file
  • Custom error pages — per-server error page overrides (400, 403, 404, 405, 500, 501, 502, 504)
  • Redirections — per-location HTTP redirects with configurable status codes (301, 307, etc.)
  • Cookies — basic cookie handling in responses
  • I/O multiplexing — non-blocking I/O using poll()
  • Signal handling — graceful shutdown on SIGINT

Build

Clone the repository and make

git clone git@github.com:opheliamarboeuf/webserv.git webserv
cd webserv
make

Requires a C++98-compatible compiler (e.g. g++ or clang++).

To clean:

make clean   # remove object files
make fclean  # remove object files and binary
make re      # full rebuild

Usage

./webserv <config_file>

Example:

./webserv bigbrowser.config

Configuration

The configuration file uses an NGINX-inspired syntax. Here is the bigbrowser.config provided with the project:

client_max_body_size 10M;

server {
    listen 127.0.0.1:8080;
    server_name bigbrowser;
    index index.html;
    root /www/html;

    error_page 404 www/html/errors/404.html;
    error_page 403 www/html/errors/403.html;
    error_page 405 www/html/errors/405.html;
    error_page 500 www/html/errors/500.html;
    error_page 502 www/html/errors/502.html;
    error_page 504 www/html/errors/504.html;

    location /cgi-bin/ {
        root /www;
        cgi_path /usr/bin/env;
        cgi_extension .sh .py;
    }

    location /data {
        root /www/html/data;
        index fallback.html;
        autoindex on;
    }

    location /uploads {
        upload_enabled on;
        upload_path /www/uploads/entry.txt;
        autoindex on;
        root /www/uploads;
        allowed_methods GET POST DELETE;
    }

    location /test_allowed {
        allowed_methods POST;
        autoindex on;
        root /www/test;
    }

    location /test_redirect {
        return 307 /redirected.html;
        root /www/test_redirect;
    }

    location /save {
        root /www/save/;
        allowed_methods DELETE;
    }
}

Supported directives

Directive Scope Description
listen server [ip:]port to listen on
server_name server One or more hostnames
root server / location Filesystem root for requests
index server / location Default file(s) for directory requests
client_max_body_size global / server Max body size (e.g. 10M, 512K)
error_page global / server Custom error pages for HTTP codes
allowed_methods location GET, POST, DELETE
autoindex location on / off — directory listing
upload_enabled location on / off
upload_path location Path where uploaded content is stored
cgi_extension location Extensions triggering CGI (e.g. .sh .py)
cgi_path location Interpreter used to run CGI scripts
return location HTTP redirection (301, 302, 307, 308)

Features overview

Feature How to test
Static file serving GET http://127.0.0.1:8080/
Directory listing GET http://127.0.0.1:8080/data/
File upload POST form at /post.html → stored in www/uploads/entry.txt
File deletion DELETE http://127.0.0.1:8080/uploads/entry.txt
HTTP redirection (307) GET http://127.0.0.1:8080/test_redirect/
Method restriction GET http://127.0.0.1:8080/test_allowed/ → 405
Shell CGI GET http://127.0.0.1:8080/cgi-bin/start.sh
Python CGI GET http://127.0.0.1:8080/cgi-bin/home_redirect.py
Cookie session Fill form at /get_info.html → cookies set via set_cookies.sh
CGI timeout (504) GET http://127.0.0.1:8080/cgi-bin/timeout.sh
Custom error pages Request a non-existent path → custom 404 page

Architecture

  • Event loop — single-threaded server using poll() for I/O multiplexing (server + clients)
  • Connections — one request per connection (Connection: close), clients handled via a state-based Client class
  • Request parsing — incremental parsing:
    • headers read until \r\n\r\n
    • support for Content-Length and chunked bodies
    • request validation before processing
  • Routing — longest-prefix match on location blocks
  • CGI executionfork() + execve() with pipes:
    • POST body sent via stdin
    • output read via stdout
    • timeout: 5s → 504 Gateway Timeout
  • Error handling — centralized via makeError():
    • custom error pages if configured
    • fallback to default HTML responses
  • Security checks — path normalization, access control (stat, access), body size limits

Why poll()

poll() is used to implement a single-threaded, event-driven server.
It allows handling multiple client sockets without blocking on I/O, while remaining portable and simpler than platform-specific alternatives such as epoll.


Project Structure

webserv/
├── inc/              # Header files
├── src/
│   ├── cgi/          # CGI execution
│   ├── config/       # Configuration parsing
│   ├── request/      # HTTP request parsing
│   ├── response/     # HTTP response building
│   ├── server/       # Server loop, client handling
│   └── webserv/      # Entry point
└── www/              # Web root (HTML, CGI scripts, uploads)

About

Custom HTTP/1.1 web server in C++98 with CGI support, virtual servers, file upload, autoindex, and event-driven architecture using poll()

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages