6.2 KiB
6.2 KiB
AGENTS.md - Rust HTTP Server Project Guide
This file provides essential information for agentic coding agents working on the rhttpd project.
Project Overview
rhttpd is a high-performance, configurable HTTP server written in Rust that supports:
- Multi-site hosting on a single port
- Multiple proxy types (reverse, forward, TCP)
- JavaScript dynamic configuration
- Static file serving with MIME type detection
Build, Test, and Development Commands
Core Commands
# Build the project
cargo build
# Build with optimizations
cargo build --release
# Run the server
cargo run
# Run tests
cargo test
# Run a single test (replace test_name with actual test)
cargo test test_name
# Run tests with output
cargo test -- --nocapture
# Check code without building
cargo check
# Format code
cargo fmt
# Run clippy lints
cargo clippy
# Run clippy with all targets and features
cargo clippy --all-targets --all-features
# Generate documentation
cargo doc --open
# Clean build artifacts
cargo clean
Code Style Guidelines
General Rust Conventions
- Use
rustfmtfor formatting (runcargo fmtbefore commits) - Follow Rust 2024 edition standards
- Use
cargo clippyto catch common issues and improve code
Imports and Dependencies
- Group imports in the following order:
- Standard library imports (
std::*) - Third-party crate imports
- Local module imports (
crate::*)
- Standard library imports (
- Use explicit imports rather than glob imports where possible
- Prefer
use crate::module::Item;overuse super::module::Item;
Naming Conventions
- Functions and variables:
snake_case - Types and structs:
PascalCase - Constants:
SCREAMING_SNAKE_CASE - Modules:
snake_case - File names:
snake_case.rs
Error Handling
- Use
Result<T, E>for functions that can fail - Create custom error types using
thiserrororanyhowwhen needed - Use
?operator for error propagation - Handle errors gracefully with proper logging
- Avoid using
unwrap()orexpect()in production code
Async/Await Patterns
- Use
async/awaitfor asynchronous operations - Prefer
tokioruntime for async operations - Use
.awaitinstead of blocking calls in async contexts - Handle async errors with
Resulttypes
Struct and Enum Design
- Use
#[derive(Debug, Clone, PartialEq, Eq)]where appropriate - Implement
Defaultfor structs with sensible defaults - Use
serdederives for configuration structs:#[derive(Debug, Clone, Serialize, Deserialize)] - Use builder pattern for complex configuration
Memory Management
- Use
Arc<RwLock<T>>for shared configuration that needs concurrent access - Use
Arc<Mutex<T>>when exclusive access is needed - Prefer borrowing over cloning when possible
- Use
Cow<str>for string data that might be borrowed or owned
Module Organization
- Keep modules focused and cohesive
- Use
mod.rsfor directory modules - Declare public APIs with
pubkeyword - Use
pub(crate)for internal APIs shared across modules
Testing Guidelines
- Write unit tests for all public functions
- Use
#[cfg(test)]for test modules - Use integration tests in
tests/directory for end-to-end testing - Mock external dependencies in tests
- Use
tokio::testfor async tests
Documentation
- Document all public APIs with
///doc comments - Use
#[doc]attributes for module-level documentation - Include examples in doc comments where helpful
- Use
cargo docto verify documentation builds correctly
Performance Considerations
- Use
Vec<T>for collections when size is known - Use
Stringfor owned string data - Avoid unnecessary allocations
- Use
&strfor string references when possible - Profile with
cargo flamegraphfor performance optimization
Security Best Practices
- Validate all external inputs
- Use type-safe configurations
- Avoid unsafe code unless absolutely necessary
- Sanitize file paths to prevent directory traversal
- Implement rate limiting for proxy endpoints
Project Structure
rhttpd/
├── src/
│ ├── main.rs # Application entry point
│ ├── lib.rs # Library root (if applicable)
│ ├── server/ # Server implementation
│ ├── config/ # Configuration management
│ ├── proxy/ # Proxy implementations
│ └── js_engine/ # JavaScript integration
├── tests/ # Integration tests
├── doc/ # Documentation and requirements
├── Cargo.toml # Project configuration
└── AGENTS.md # This file
Key Dependencies (as specified in requirements)
Core Runtime
tokio- Async runtimehyperoraxum- HTTP server frameworktower- Middleware and service abstractions
Configuration
serde- Serialization/deserializationserde_json- JSON supporttoml- TOML configuration support
Static Files
tower-http- HTTP service utilitiesmime_guess- MIME type detection
Proxy Support
reqwest- HTTP client for reverse proxytokio-util- Utilities for async I/Otokio-native-tls- TLS support
JavaScript Engine
- Choose one:
deno_core,rquickjs, orboa_engine
Development Workflow
- Run
cargo checkto verify code compiles - Run
cargo clippyto catch issues - Run
cargo fmtto format code - Run
cargo testto verify tests pass - Commit changes with descriptive messages
Testing Strategy
- Unit tests for individual components
- Integration tests for end-to-end functionality
- Performance tests for proxy operations
- Configuration validation tests
Common Patterns
Configuration Loading
#[derive(Debug, Deserialize)]
struct ServerConfig {
port: u16,
sites: HashMap<String, SiteConfig>,
}
Error Types
#[derive(Debug, thiserror::Error)]
enum ServerError {
#[error("Configuration error: {0}")]
Config(#[from] ConfigError),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
Async Service Pattern
#[async_trait]
trait ProxyService {
async fn handle_request(&self, req: Request<Body>) -> Result<Response<Body>, ServerError>;
}
Remember to run cargo fmt and cargo clippy before committing changes!