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.
- 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
- 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
- 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
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
- Linux operating system (for epoll support)
- GCC compiler with C++98 support
- Python 3 (for CGI scripts)
- PHP (for CGI scripts)
-
Clone the repository:
git clone <repository-url> cd webserv
-
Build the project:
make
-
Clean build artifacts:
make clean
-
Rebuild from scratch:
make re
The webserver uses TOML format for configuration. Create a config.toml file in the project root:
# 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"| 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 | "" |
-
With default configuration:
./webserv
-
With custom configuration:
./webserv config.toml
-
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/
-
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
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
}
}
}-
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
The project includes test scripts in the config_parser/tests/ directory for configuration parsing validation.
-
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
The server includes debug output for:
- Request parsing
- Configuration loading
- Connection handling
- CGI execution
- GET: Retrieve resources
- POST: Submit data
- DELETE: Remove resources
- 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
REQUEST_METHODQUERY_STRINGCONTENT_LENGTHCONTENT_TYPESCRIPT_NAMEPATH_INFOHTTP_*headers
This project is part of the 42 school curriculum and follows the 42 coding standards.
- Saad ERRAOUI - Initial work (2024-12-22)
- BOUZID Hicham - Connection management and event handling
- Weismann - CGI, TOML Parser, Internal Logic and improvements
- 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