A high-performance HTTP/1.1 web server written in C++98, implementing core web server functionality with support for multiple virtual hosts, CGI execution, and comprehensive error handling.
๐ Features
Core Functionality
- HTTP/1.1 Protocol Support: Full implementation of HTTP/1.1 specification
- Multiple Virtual Hosts: Support for multiple server blocks with different configurations
- Epoll-based I/O: High-performance event-driven architecture using Linux epoll
- Connection Management: Automatic connection handling with timeout support
- Request Parsing: Robust HTTP request parsing with header validation
- Response Generation: Dynamic HTTP response generation with proper status codes
Advanced Features
- CGI Support: Execute Python and PHP scripts with proper environment setup
- Static File Serving: Serve static files with proper MIME type detection
- Directory Listing: Auto-index functionality for directory browsing
- Error Pages: Custom error pages for various HTTP status codes
- Upload Support: File upload functionality with configurable limits
- Redirection: HTTP redirection support
- Request Methods: Support for GET, POST, DELETE HTTP methods
Configuration
- TOML Configuration: Human-readable configuration file format
- Flexible Routing: Configurable routes with method restrictions
- Server Blocks: Multiple server configurations with different ports and hostnames
- Error Page Mapping: Custom error pages for different status codes
๐ Project Structure
webserv/
โโโ main.cpp # Main entry point
โโโ Makefile # Build configuration
โโโ config_parser/ # Configuration parsing
โ โโโ Webserv.cpp # Main configuration parser
โ โโโ server.cpp # Server configuration handling
โ โโโ utilities/ # Parser utilities
โ โโโ tests/ # Parser tests
โโโ HttpRequest/ # HTTP request handling
โ โโโ HttpRequest.cpp # Request object implementation
โ โโโ HttpRequest.hpp # Request class definition
โ โโโ HttpRequestParser.cpp # Request parsing logic
โ โโโ HttpRequestParser.hpp # Parser interface
โโโ HttpResponse/ # HTTP response handling
โ โโโ HttpResponse.cpp # Response object implementation
โ โโโ HttpResponse.hpp # Response class definition
โ โโโ HttpResponseUtilities.cpp # Response utilities
โ โโโ GetMethod.cpp # GET method implementation
โโโ Connection/ # Connection management
โ โโโ Connection.cpp # Connection handling
โ โโโ Connection.hpp # Connection class definition
โโโ CGI/ # CGI execution
โ โโโ Cgi.cpp # CGI script execution
โโโ SetupServer/ # Server setup
โ โโโ MultipSockets.cpp # Multiple socket handling
โ โโโ StartServerSetup.cpp # Server initialization
โ โโโ includes.hpp # Setup includes
โโโ Includes/ # Header files
โโโ www/ # Web root directory
โ โโโ index.html # Default index page
โ โโโ html/ # Web content
โ โโโ pepe/ # Test content
โ โ โโโ v1/ # Version 1 content
โ โ โโโ script.py # Python CGI script
โ โ โโโ script.php # PHP CGI script
โ โโโ ErrorPages/ # Custom error pages
โโโ nginx/ # Nginx configuration examples
๐ ๏ธ Installation
Prerequisites
- Linux operating system (for epoll support)
- GCC compiler with C++98 support
- Python 3 (for CGI scripts)
- PHP (for CGI scripts)
Building the Project
-
Clone the repository:
git clone <repository-url> cd webserv
-
Build the project:
-
Clean build artifacts:
-
Rebuild from scratch:
โ๏ธ Configuration
The webserver uses TOML format for configuration. Create a config.toml file in the project root:
Basic Configuration Example
# Global settings default_max_body_size = "123" # Server block [[server]] host = "127.0.0.1" port = [9090, 9091, 8080] server_name = ["127.0.0.1:8080"] max_body_size = "23" # Error pages [[server.error_pages]] 301 = "301.html" 400 = "400.html" 403 = "403.html" 404 = "404.html" 405 = "405.html" 500 = "500.html" 505 = "505.html" # Route configuration [[server.route]] path = "/" methods = ["GET", "POST", "DELETE"] autoindex = true index = "index.html" root = "./www/html/pepe/v1" CGI_extensions = {py = "/usr/bin/python3", php = "/usr/bin/php"} upload = "./www/html/uploads/" redirection = "lmao"
Configuration Options
| Option | Description | Default |
|---|---|---|
host |
Server host address | "127.0.0.1:port" |
port |
Server port(s) | [8080] |
server_name |
Server name(s) | [] |
max_body_size |
Maximum request body size | "123" |
path |
Route path | "/" |
methods |
Allowed HTTP methods | ["GET"] |
autoindex |
Enable directory listing | false |
index |
Default index file | "index.html" |
root |
Document root directory | "./www" |
CGI_extensions |
CGI script extensions and interpreters | {} |
upload |
Upload directory | "./uploads" |
redirection |
Redirect URL | "" |
๐ Usage
Starting the Server
-
With default configuration:
-
With custom configuration:
Testing the Server
-
Basic HTTP request:
curl http://localhost:8080/
-
CGI script execution:
curl http://localhost:8080/script.py curl http://localhost:8080/script.php
-
File upload (if configured):
curl -X POST -F "file=@local_file.txt" http://localhost:8080/upload/ -
Different HTTP methods:
curl -X GET http://localhost:8080/ curl -X POST http://localhost:8080/ curl -X DELETE http://localhost:8080/
๐ง Architecture
Core Components
-
Main Loop (
main.cpp):- Server initialization
- Signal handling
- Configuration loading
-
Connection Manager (
Connection/):- Client connection handling
- Request/response lifecycle
- Timeout management
-
HTTP Parser (
HttpRequest/):- Request line parsing
- Header parsing
- Body handling
-
Response Generator (
HttpResponse/):- Status code generation
- Header construction
- Body formatting
-
CGI Executor (
CGI/):- Script execution
- Environment setup
- Output handling
Event-Driven Architecture
The server uses Linux epoll for efficient I/O multiplexing:
// Epoll event loop while (true) { int n = epoll_wait(epollfd, events, MAX_EPOLL_EVENT, timeout); for (int i = 0; i < n; i++) { if (events[i].events & EPOLLIN) { // Handle incoming data } if (events[i].events & EPOLLOUT) { // Handle outgoing data } } }
๐งช Testing
Manual Testing
-
Basic Functionality:
- Start the server
- Access via browser:
http://localhost:8080 - Verify static file serving
-
CGI Testing:
- Access Python script:
http://localhost:8080/script.py - Access PHP script:
http://localhost:8080/script.php - Verify script execution
- Access Python script:
-
Error Handling:
- Access non-existent file:
http://localhost:8080/notfound - Verify custom error pages
- Access non-existent file:
-
Method Testing:
- Test different HTTP methods
- Verify method restrictions
Automated Testing
The project includes test scripts in the config_parser/tests/ directory for configuration parsing validation.
๐ Debugging
Common Issues
-
Port Already in Use:
# Check if port is in use netstat -tlnp | grep :8080 # Kill process using port sudo fuser -k 8080/tcp
-
Permission Issues:
# Make sure CGI scripts are executable chmod +x www/html/pepe/script.py chmod +x www/html/pepe/script.php -
Configuration Errors:
- Check TOML syntax
- Verify file paths exist
- Ensure proper indentation
Debug Output
The server includes debug output for:
- Request parsing
- Configuration loading
- Connection handling
- CGI execution
๐ API Reference
HTTP Methods Supported
- GET: Retrieve resources
- POST: Submit data
- DELETE: Remove resources
Status Codes
- 200: OK
- 301: Moved Permanently
- 400: Bad Request
- 403: Forbidden
- 404: Not Found
- 405: Method Not Allowed
- 408: Request Timeout
- 413: Payload Too Large
- 500: Internal Server Error
- 505: HTTP Version Not Supported
CGI Environment Variables
REQUEST_METHODQUERY_STRINGCONTENT_LENGTHCONTENT_TYPESCRIPT_NAMEPATH_INFOHTTP_*headers
๐ License
This project is part of the 42 school curriculum and follows the 42 coding standards.
๐ฅ Authors
- Saad ERRAOUI - Initial work (2024-12-22)
- BOUZID Hicham - Connection management and event handling
- Weismann - CGI, TOML Parser, Internal Logic and improvements
๐ Acknowledgments
- 42 school for the project requirements
- Nginx for configuration inspiration
- Linux epoll documentation
- HTTP/1.1 RFC 2616 specification
Note: This webserver is designed for educational purposes and follows the 42 school coding standards. It implements core web server functionality while maintaining clean, readable code structure. This was made PURELY for the sake of learning about the internal work of servers, and not made for production