Zircon
A lightweight, event-driven HTTP server written in C.
Note: This is an experimental project developed with AI assistance. Not recommended for production use.
Features
- Event-driven architecture using kqueue (macOS/BSD) or epoll (Linux)
- Zero-copy file transfer via platform-native sendfile
- HTTP Keep-Alive for connection reuse
- Security hardened:
- Path traversal prevention
- File type restrictions
- Security headers (CSP, X-Frame-Options, HSTS, etc.)
- Rate limiting
- Request size limits with proper 413 responses
- HTTP caching with ETag support and Cache-Control headers
- MIME type detection by extension and magic bytes
- Graceful shutdown on SIGTERM/SIGINT
- Connection timeouts for idle connections
- Config file support
Quick Start
# Build make # Run (listens on 127.0.0.1:8000 by default) ./bin/zircon # Run with options ./bin/zircon --port 8080 --bind 0.0.0.0 --keep-alive # Load from config file ./bin/zircon --config conf/server.conf # Show all options ./bin/zircon --help
Usage
Usage: ./bin/zircon [OPTIONS]
Options:
--config FILE Load config from FILE
--port PORT Listen on PORT (default: 8000)
--bind ADDR Bind to ADDR (default: 127.0.0.1)
--root DIR Serve files from DIR (default: www)
--timeout SEC Connection timeout in seconds (default: 30)
--keep-alive Enable HTTP Keep-Alive
--workers N Run with N worker threads (experimental)
--platform-info Show platform capabilities
--help Show this help
Configuration File
Example conf/server.conf:
# Network port = 8000 bind = 127.0.0.1 # Paths root = www # Limits timeout = 30 max_request_size = 8192 # Features keep_alive = false
Project Structure
zircon/
├── src/
│ ├── main.c # Entry point, CLI parsing
│ ├── server_async.c # Event-driven server core
│ ├── http.c # HTTP parsing, MIME types, ETag
│ ├── rate_limiter.c # IP-based rate limiting
│ ├── security_headers.c # Security header generation
│ ├── logger.c # Logging system
│ └── platform/ # Platform abstraction layer
│ ├── event_kqueue.c # macOS/BSD event loop
│ ├── event_epoll.c # Linux event loop
│ ├── sendfile.c # Zero-copy file transfer
│ ├── thread_pool.c # Worker thread pool
│ └── thread.c # Thread utilities
├── include/ # Header files
├── test/ # Test suite
├── www/ # Default web root
├── conf/ # Configuration files
└── Makefile
Building
Requirements
- GCC or Clang
- POSIX-compliant OS (Linux, macOS, FreeBSD)
- pthread library
Build Commands
make # Release build make DEBUG=1 # Debug build with symbols make clean # Clean build artifacts make test # Run test suite
Testing
# Run all tests make test # Run specific test categories make test-unit make test-security make test-performance # Run edge case security tests ./test/edge_case_test.sh
Architecture
Event Loop
The server uses a single-threaded event loop by default:
- Accept connections via non-blocking socket
- Register client fd with kqueue/epoll
- On read event: parse HTTP request, validate, serve file
- Use sendfile() for zero-copy transfer
- With keep-alive: reset connection state and continue
- Without keep-alive: close connection
Security Model
All requests pass through multiple validation layers:
- Path validation: Blocks
.., encoded traversal, null bytes - Method restriction: Only GET and HEAD allowed
- File type check: Whitelist of allowed extensions
- Request size limit: Returns 413 for oversized requests
- Rate limiting: Per-IP request throttling
- Response headers: CSP, HSTS, X-Frame-Options, etc.
Performance
Single-threaded async mode on macOS (Apple Silicon):
- ~15,000 requests/second with 50 concurrent connections
- Sub-millisecond latency for small files
Limitations
- No HTTPS (TLS) support
- No HTTP/2
- No dynamic content / CGI
- Single-threaded by default
License
MIT License
Acknowledgments
Developed as an experiment in AI-assisted systems programming.