A multithreaded HTTP/1.1 server written from scratch in Rust. It serves static files from a configurable public directory and implements HTTP protocol parsing manually.
- HTTP/1.1 request parsing (method, path, query string, headers, body)
- Request body parsed from
Content-Length+Content-Type; represented asTextorBinary - Static file serving (HTML, CSS, JSON, images, …) from a
public/directory - Auto-detected
Content-Typeheader based on file extension Content-Lengthheader included in every response405 Method Not Allowedfor non-GET requests;404for missing files- Custom
404.htmlpage served when present inpublic/ - Directory traversal attack prevention
- Dynamic read buffer: headers up to 8 KB, body up to 1 MB
- 5-second read timeout per connection
- Configurable bind address and port via environment variables
- Centralised error handling via
thiserror - Query string parsing with multi-value support per key
- Configurable log levels (
DEBUG,INFO,WARN,ERROR) vialog+env_logger - Structured routing via a
Routerwithget()/post()registration, replacing manual pathmatchblocks - Fixed-size
ThreadPool(manual,std::thread+std::sync::mpsc) so multiple connections are handled concurrently
src/
├── main.rs # Entry point, server startup
├── config.rs # Config struct (env vars + .env file)
├── router.rs # Router: maps method + path to a handler
├── server.rs # TCP server and Handler trait
├── thread_pool.rs # Manual ThreadPool for concurrent connection handling
├── website_handler.rs # Static file handler
└── http/
├── mod.rs # Module exports
├── error.rs # ParseError (thiserror)
├── method.rs # Method enum (GET, POST, PUT, …)
├── request.rs # HTTP request parsing
├── request_body.rs # RequestBody enum (Text / Binary)
├── response.rs # HTTP response building
├── status_code.rs # StatusCode enum with reason phrases
├── query_string.rs # Query string parsing
└── headers.rs # HTTP headers parsing
public/
├── index.html
├── 404.html
├── style.css
└── informations.json
Rust and Cargo installed. Installation guide: https://www.rust-lang.org/learn/get-started
git clone https://github.com/federicobaldini/http-server
cd http-server
cargo runThe server starts on 127.0.0.1:5000 by default.
| Environment Variable | Description | Default |
|---|---|---|
PUBLIC_PATH |
Absolute path to the static files directory | ./public |
HOST |
IP address the server binds to | 127.0.0.1 |
PORT |
TCP port the server listens on | 5000 |
MAX_HEADER_SIZE |
Max request header bytes | 8192 |
MAX_BODY_SIZE |
Max request body bytes | 1048576 |
READ_TIMEOUT_SECS |
Idle connection timeout in seconds | 5 |
THREAD_POOL_SIZE |
Number of worker threads handling connections concurrently | 4 |
RUST_LOG |
Log level (error, warn, info, debug, trace) |
info |
All variables can also be set in a .env file at the project root (loaded automatically via dotenvy).
Example:
PUBLIC_PATH=/var/www/html HOST=0.0.0.0 PORT=8080 RUST_LOG=debug cargo run- Fixed-size thread pool: connections beyond
THREAD_POOL_SIZEqueue for the next free worker - No keep-alive support (connection closes after each response)
- No HTTPS support