# 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 ```bash # 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 `rustfmt` for formatting (run `cargo fmt` before commits) - Follow Rust 2024 edition standards - Use `cargo clippy` to catch common issues and improve code ### Imports and Dependencies - Group imports in the following order: 1. Standard library imports (`std::*`) 2. Third-party crate imports 3. Local module imports (`crate::*`) - Use explicit imports rather than glob imports where possible - Prefer `use crate::module::Item;` over `use 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` for functions that can fail - Create custom error types using `thiserror` or `anyhow` when needed - Use `?` operator for error propagation - Handle errors gracefully with proper logging - Avoid using `unwrap()` or `expect()` in production code ### Async/Await Patterns - Use `async`/`await` for asynchronous operations - Prefer `tokio` runtime for async operations - Use `.await` instead of blocking calls in async contexts - Handle async errors with `Result` types ### Struct and Enum Design - Use `#[derive(Debug, Clone, PartialEq, Eq)]` where appropriate - Implement `Default` for structs with sensible defaults - Use `serde` derives for configuration structs: ```rust #[derive(Debug, Clone, Serialize, Deserialize)] ``` - Use builder pattern for complex configuration ### Memory Management - Use `Arc>` for shared configuration that needs concurrent access - Use `Arc>` when exclusive access is needed - Prefer borrowing over cloning when possible - Use `Cow` for string data that might be borrowed or owned ### Module Organization - Keep modules focused and cohesive - Use `mod.rs` for directory modules - Declare public APIs with `pub` keyword - 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::test` for 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 doc` to verify documentation builds correctly ### Performance Considerations - Use `Vec` for collections when size is known - Use `String` for owned string data - Avoid unnecessary allocations - Use `&str` for string references when possible - Profile with `cargo flamegraph` for 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 runtime - `hyper` or `axum` - HTTP server framework - `tower` - Middleware and service abstractions ### Configuration - `serde` - Serialization/deserialization - `serde_json` - JSON support - `toml` - TOML configuration support ### Static Files - `tower-http` - HTTP service utilities - `mime_guess` - MIME type detection ### Proxy Support - `reqwest` - HTTP client for reverse proxy - `tokio-util` - Utilities for async I/O - `tokio-native-tls` - TLS support ### JavaScript Engine - Choose one: `deno_core`, `rquickjs`, or `boa_engine` ## Development Workflow 1. Run `cargo check` to verify code compiles 2. Run `cargo clippy` to catch issues 3. Run `cargo fmt` to format code 4. Run `cargo test` to verify tests pass 5. 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 ```rust #[derive(Debug, Deserialize)] struct ServerConfig { port: u16, sites: HashMap, } ``` ### Error Types ```rust #[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 ```rust #[async_trait] trait ProxyService { async fn handle_request(&self, req: Request) -> Result, ServerError>; } ``` Remember to run `cargo fmt` and `cargo clippy` before committing changes!