A lightweight web server written in C, built from scratch to better understand networking and the HTTP protocol at a low level.
- GCC compiler
- Make
- Linux/Unix environment
-
Clone the repository:
git clone <repository-url> cd c-web-server
-
Build and run in one command:
make cbr
This single command will:
- Clean previous builds (
clean) - Compile the project (
build) - Run the web server (
run)
- Clean previous builds (
-
Alternative commands:
# Build only make # Clean build files make clean # Run the server (after building) make run # Format code make format
-
Configuration:
- The server reads configuration from
cws.conf - Static files are served from the
public/directory - Default port and other settings can be configured in the config file
- The server reads configuration from
-
Access the server:
- Open your browser and navigate to
http://localhost:PORT(checkcws.conffor the configured port)
- Open your browser and navigate to
-
Basic Server
- Create a simple TCP server that listens on a port.
- Respond with a fixed static response (e.g., "Hello, World!").
-
Serve Static Files & Logging
- Add ability to serve static files (HTML, CSS, images).
- Add autoindexing for directories without an index file. (low priority)
- Implement a basic logging system to track requests and responses.
- Add basic configuration file support.
-
Proxy Features
- Add reverse proxy capabilities to forward requests to other applications (Node.js, Python, Java, etc.).
-
Large Request Handling
- Fix buffer overflow issues when sending large files.
- (1/2 i didnt handle large php request yet and i dont think that i will do it)Handle receiving large requests (buffer overflow). (i will do this after multi-threading to avoid conflicts)
-
Multi-Threading Support
- Enable the server to handle multiple clients concurrently using thread pool.
-
Security & HTTPS
- Add basic security checks and input validation.
- Implement TLS/SSL support for HTTPS.
-
Dynamic Content (PHP Support)
- Support executing PHP scripts and returning the output.
- Inhance the multi threading system (add event loops)
- Add caching support.
- Support HTTP/2 & HTTP/3.
- Add WebSocket support.
The server uses a TOML configuration file (cws.conf) to define its behavior. Here's a complete breakdown of all configuration options:
[server]
host = "0.0.0.0" # IP address to bind to (0.0.0.0 for all interfaces)
port = 8080 # Port to listen on
max_connections = 100 # Maximum number of concurrent connections
workers = 4 # Number of worker threads (default: 1)
default_index_name = "index.html" # Default file to serve for directories
php_cgi_path = "/usr/bin/php-cgi" # Path to PHP CGI binary (optional, NULL to disable PHP)[logging]
level = "DEBUG" # Log level: DEBUG, INFO, WARN, ERROR
use_colors = true # Enable colored output in logs
time_format = "%Y-%m-%d %H:%M:%S" # Timestamp format (strftime format)
output = "stdout" # Log output: "stdout", "stderr", or file pathRoutes define how different URL paths are handled. You can define multiple routes using the [[routes]] syntax:
# Static file serving
[[routes]]
path = "/" # URL path to match
root = "./public" # Directory to serve files from
index = "index.html" # Default file for directories
autoindex = false # Enable/disable directory listing
methods = ["GET"] # Allowed HTTP methods (optional)
# Reverse proxy
[[routes]]
path = "/api" # URL path to proxy
proxy_pass = "http://localhost:3000" # Backend server URL
methods = ["GET", "POST"] # Allowed HTTP methods
# Static files with directory listing
[[routes]]
path = "/static/"
root = "./static"
index = "index.html"
autoindex = true # Shows directory contents if no index file
methods = ["GET"]-
Static File Routes: Serve files from a local directory
- Requires:
path,root - Optional:
index,autoindex,methods
- Requires:
-
Proxy Routes: Forward requests to another server
- Requires:
path,proxy_pass - Optional:
methods
- Requires:
Basic static server:
[server]
port = 8080
[logging]
level = "INFO"
[[routes]]
path = "/"
root = "./public"With proxy for API:
[server]
port = 8080
[[routes]]
path = "/"
root = "./public"
[[routes]]
path = "/api"
proxy_pass = "http://localhost:3000"
methods = ["GET", "POST", "PUT", "DELETE"]All contributions are welcome! Whether you're fixing bugs, adding new features, improving documentation, or suggesting enhancements, your help is appreciated.