BWS (Ben's Web Server)
A high-performance, multi-site web server built with Pingora, Cloudflare's battle-tested proxy framework.
🚀 Features
- Multi-Site Support: Host multiple websites on different ports with individual configurations
- Configurable Headers: Set custom HTTP headers per site via TOML configuration
- High Performance: Built on Pingora for enterprise-grade performance and reliability
- Health Monitoring: Built-in health check endpoints for monitoring
- Security Focused: Comprehensive security auditing and dependency management
- Easy Configuration: Simple TOML-based configuration system
📦 Installation
From crates.io
From Source
🔧 Quick Start
- Create a configuration file (
bws_config.toml):
[[]]
= "main"
= 8080
= "http://localhost:3000"
[]
= "BWS"
= "main"
[[]]
= "api"
= 8081
= "http://localhost:4000"
[]
= "v1"
= "api"
- Run the server:
- Test your setup:
# Test main site
# Test API site
# Health check
[]
= "BWS Multi-Site Server"
# Main site with production headers
[[]]
= "main"
= "localhost"
= 8080
= "static"
= true
[]
= "BWS Main Site"
= "BWS/1.0"
= "main"
= "production"
# Blog site with custom headers
[[]]
= "blog"
= "blog.localhost"
= 8081
= "static-blog"
[]
= "BWS Blog"
= "BWS/1.0"
= "blog"
= "blog-content"
= "BWS Team"
# API documentation site with CORS headers
[[]]
= "api"
= "api.localhost"
= 8082
= "static-api"
= true
[]
= "BWS API Documentation"
= "BWS/1.0"
= "api-docs"
= "v1.0"
= "*"
= "GET, POST, PUT, DELETE, OPTIONS"
# Development site with debug headers
[[]]
= "dev"
= "localhost"
= 8083
= "static-dev"
[]
= "BWS Development Site"
= "BWS/1.0"
= "development"
= "development"
= "enabled"
Configuration Options
- server.name: Display name for the server
- sites: Array of site configurations
- sites.name: Unique identifier for the site
- sites.hostname: Hostname for virtual host routing
- sites.port: Port number for the site
- sites.static_dir: Directory containing static files
- sites.default: Mark as default site (optional)
- sites.api_only: API-only site, no static files (optional)
- sites.headers: Custom HTTP headers to include in all responses for this site
Configurable Headers
Each site can define custom HTTP headers that will be included in all responses from that site:
- Security Headers: CORS, CSP, security policies
- Custom Headers: Site identification, versioning, environment info
- API Headers: API versioning, CORS for API sites
- Debug Headers: Development flags, debug information
- Branding Headers: Custom site branding and identification
Development site
[[sites]] name = "dev" hostname = "localhost" port = 8083 static_dir = "static-dev"
### Configuration Options
- **name**: Unique identifier for the site
- **hostname**: Hostname for virtual host matching
- **port**: Port number to listen on
- **static_dir**: Directory containing static files for this site
- **default**: (optional) Set to true for the default/fallback site
- **api_only**: (optional) Set to true for API-only sites
## Available Endpoints
### Multi-Site Support
The server can host multiple websites simultaneously:
- **Main Site** (localhost:8080) - Original BWS website
- **Blog Site** (blog.localhost:8081) - Blog content with different styling
- **API Docs** (api.localhost:8082) - API documentation with dark theme
- **Dev Site** (localhost:8083) - Development environment
### Static Website Endpoints
Each site serves its own static content:
- **GET /** - Serves the site's `index.html` from its static directory
- **GET /about.html** - About page (if available in static directory)
- **GET /contact.html** - Contact page (if available in static directory)
- **GET /static/*** - Serves static assets (CSS, JS, images, etc.) with cache headers
### API Endpoints
#### Sites Information
- **GET /api/sites** - Returns information about all configured sites
```json
{
"server": "BWS Multi-Site Server",
"sites": [
{
"name": "main",
"hostname": "localhost",
"port": 8080,
"static_dir": "static",
"url": "http://localhost:8080"
}
],
"total_sites": 4
}
Health Check
- GET /api/health - Returns server health status (available on all sites)
File Content API
- GET /api/file?path=filename - Returns the content of the specified file
Error Handling
- 404 Not Found - Returns JSON error for non-existent endpoints
Getting Started
Prerequisites
- Rust 1.70+ (2021 edition)
- Cargo
Dependencies
pingora- High-performance proxy frameworkasync-trait- Async trait supportserde&serde_json- JSON serializationchrono- Date/time handlingtokio- Async runtimeenv_logger&log- Loggingtoml- Configuration file parsing
Building
Configuration
- Copy and modify
config.tomlto configure your sites - Create static directories for each site (e.g.,
static-blog/,static-api/) - Add HTML, CSS, JS files to each static directory
Running
# Start the multi-site server
RUST_LOG=info
The server will start multiple services based on your configuration.
Testing Multiple Sites
# Run comprehensive multi-site test
# Test configurable headers functionality
# Test individual sites
# Test with virtual host headers
# Check sites configuration (includes header config)
# Test site-specific headers
Virtual Host Setup (Optional)
Add entries to /etc/hosts for easier testing:
127.0.0.1 blog.localhost
127.0.0.1 api.localhost
Then access sites via:
Project Structure
├── src/
│ ├── bin/
│ │ └── main.rs # Server entry point and multi-site setup
│ └── lib.rs # Web server implementation with config support
├── static/ # Main site files
│ ├── index.html # Main homepage
│ ├── about.html # About page
│ ├── contact.html # Contact page
│ ├── styles.css # Website styles
│ └── script.js # Website JavaScript
├── static-blog/ # Blog site files
│ └── index.html # Blog homepage
├── static-api/ # API documentation site
│ └── index.html # API docs homepage
├── static-dev/ # Development site files
│ └── index.html # Dev homepage
├── config.toml # Multi-site configuration with headers
├── Cargo.toml # Project dependencies
├── test_multisite.sh # Multi-site test script
├── test_headers.sh # Configurable headers test script
├── test_static_server.sh # Static website test script
└── README.md # This file
API Implementation Details
WebServerService
The main service implements the ProxyHttp trait from Pingora:
request_filter(): Routes incoming requests to appropriate handlersupstream_peer(): Returns error since we handle requests locally
Request Routing
The server intelligently routes requests based on URL patterns:
/→static/index.html/static/*→ Static assets with cache headers/*.html→ HTML files from static directory/api/*→ API endpoints- Everything else → 404 error
Request Handlers
handle_static_file(): Serves static files with proper MIME types and cache headershandle_health(): Returns JSON health statushandle_file_content(): Reads and returns file contentshandle_404(): Returns JSON error for unknown endpoints
Static File Features
- MIME Type Detection: Automatic content-type detection for:
- HTML, CSS, JavaScript
- Images (PNG, JPEG, GIF, SVG, ICO)
- Fonts (WOFF, WOFF2, TTF)
- Documents (PDF, XML, TXT)
- Cache Headers:
Cache-Control: public, max-age=3600for static assets - Error Handling: Graceful 404 responses for missing files
Features
- Content-Type Headers: Proper MIME types for all file types
- Content-Length: Accurate response size calculation
- Error Handling: Graceful error responses with helpful messages
- Query Parameter Parsing: Manual parsing for file path parameter
- Logging: Request logging with method and URI
Extending the Server
To add new endpoints:
- Add a new pattern match in
request_filter() - Create a new handler method following the pattern of existing handlers
- Ensure proper error handling and response headers
Example:
"/api/new-endpoint" =>
Performance Characteristics
- Memory Efficient: Uses
Vec<u8>for response bodies to avoid borrowing issues - Async: Fully asynchronous request handling
- Zero-Copy: Efficient byte handling where possible
- Concurrent: Supports multiple simultaneous connections
Security Considerations
- File reading is currently unrestricted - consider adding path validation
- No authentication/authorization implemented
- Consider rate limiting for production use
- HTTPS support can be added through Pingora configuration
Security Status
The project uses automated security scanning via GitHub Actions. The current security status:
- ✅ Active Monitoring: Weekly security audits via
cargo audit - ✅ Dependency Review: Automated dependency review on pull requests
- ⚠️ Known Issue: One accepted vulnerability (RUSTSEC-2024-0437) - see
SECURITY.md
Security Documentation: See SECURITY.md for detailed security status and known issues.
Monitoring Script: Run ./scripts/monitor-deps.sh to check for dependency updates and security status.
Security Workflow: The CI pipeline automatically scans for new vulnerabilities while ignoring documented accepted risks.