Skip to content

Repository files navigation

Concurrent HTTP/1.1 Server

CI

A concurrent HTTP/1.1 server built from scratch in C++20 using POSIX sockets, a bounded worker-thread pool, and zero external web frameworks.

Why this exists

This project demonstrates systems-level engineering: raw socket programming, HTTP protocol parsing per RFC 9112, thread-safe concurrency primitives, and operational observability — the skills that matter for backend infrastructure roles.

Features

  • HTTP/1.1 request parsing (GET, HEAD, POST)
  • Static file serving with MIME type detection
  • Built-in routes: /health, /echo, /metrics
  • Bounded thread pool with backpressure (rejects under overload instead of OOM)
  • Thread-safe task queue using std::mutex + std::condition_variable
  • Graceful shutdown on SIGINT/SIGTERM
  • Security: request-size limits, path-traversal protection
  • Proper error responses: 400, 404, 405, 413, 500
  • Observability: request count, active connections, latency, error rates
  • Tested: 30+ unit/integration tests, sanitizer-clean

Quick start

# Build
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

# Run
./http_server --port 8080 --workers 4 --doc-root ../public

# Test
curl http://localhost:8080/health
curl http://localhost:8080/metrics

Build options

Flag Default Purpose
BUILD_TESTS ON Build GoogleTest suite
ENABLE_ASAN OFF AddressSanitizer (memory errors)
ENABLE_TSAN OFF ThreadSanitizer (data races)
# Run with sanitizers
cmake .. -DENABLE_ASAN=ON && make -j$(nproc) && ./http_server
cmake .. -DENABLE_TSAN=ON && make -j$(nproc) && ./http_server

Running tests

cd build
cmake .. -DBUILD_TESTS=ON
make -j$(nproc)
ctest --output-on-failure

Docker

docker build -t concurrent-http-server .
docker run -p 8080:8080 concurrent-http-server

Architecture

┌─────────────┐
│   Clients   │
└──────┬──────┘
       │ TCP connections
┌──────▼──────┐
│   Listener  │  accept() loop on main thread
└──────┬──────┘
       │ enqueue client fd
┌──────▼──────┐
│  Task Queue │  bounded, thread-safe, backpressure
└──────┬──────┘
       │ dequeue
┌──────▼──────┐
│ Thread Pool │  N worker threads
│  ┌────────┐ │
│  │Worker 1│ │  recv → parse → route → send
│  │Worker 2│ │
│  │Worker N│ │
│  └────────┘ │
└──────┬──────┘
       │ updates
┌──────▼──────┐
│   Metrics   │  atomic counters, GET /metrics
└─────────────┘

Concurrency model comparison

Model Threads Memory Latency at 1K conn Notes
Single-threaded 1 Minimal High (serial) Baseline only
Thread-per-connection ~1K ~8 GB stack Low (parallel) Doesn't scale
Bounded thread pool N (configurable) Bounded Low This project

Non-goals (and why)

  • TLS: Would obscure socket-level learning; use a reverse proxy in production
  • HTTP/2: Binary framing is a different project entirely
  • Chunked transfer: Adds parser complexity without demonstrating new systems concepts
  • Authentication: Application-layer concern, not a server-infrastructure concern

System calls explained

Call Purpose
socket() Create a TCP endpoint
setsockopt() Set SO_REUSEADDR to avoid bind failures on restart
bind() Attach socket to an address and port
listen() Mark socket as passive (accepting connections)
accept() Block until a client connects; return a new fd
recv() Read bytes from a connected socket
send() Write bytes to a connected socket
close() Release file descriptor

Benchmarks

See benchmarks/BENCHMARKS.md for full results.

Project log

Day What shipped AI usage
1 Repo setup, CMake, design doc
... ... ...

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages