Skip to content

Commit 79f909f

Browse files
committed
Update documentation and complete config hot reload
1 parent e982c65 commit 79f909f

3 files changed

Lines changed: 269 additions & 21 deletions

File tree

AGENTS.md

Lines changed: 266 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,135 @@
33
## Project Overview
44

55
**Candy** is a modern, lightweight web server written in Rust. It supports:
6-
- Static file serving
7-
- Reverse proxying
6+
7+
- Static file serving with directory listing support
8+
- Reverse proxying to backend servers
89
- Lua scripting (optional feature)
9-
- SSL/TLS encryption
10-
- Configuration reload on file change
10+
- SSL/TLS encryption (HTTPS)
11+
- HTTP/2 support
12+
- Auto-reload config on file change
1113
- Multiple virtual hosts
14+
- Single binary deployment
15+
16+
## Project Structure
17+
18+
```
19+
/home/xfy/Developer/candy/
20+
├── src/
21+
│ ├── main.rs # Entry point with server initialization
22+
│ ├── config.rs # Configuration loading and validation
23+
│ ├── cli.rs # Command-line interface parsing
24+
│ ├── consts.rs # Constant definitions (version, arch, commit info)
25+
│ ├── error.rs # Custom error types and error handling
26+
│ ├── http/
27+
│ │ ├── mod.rs # HTTP server creation and shutdown
28+
│ │ ├── serve.rs # Static file serving handler
29+
│ │ ├── reverse_proxy.rs # Reverse proxy handler
30+
│ │ ├── lua/ # Lua scripting handler (optional)
31+
│ │ ├── redirect.rs # HTTP redirect handler
32+
│ │ └── error.rs # HTTP error handling
33+
│ ├── middlewares/ # HTTP middleware (version, headers, logging)
34+
│ ├── utils/
35+
│ │ ├── mod.rs # Utility functions
36+
│ │ ├── config_watcher.rs # Configuration file watcher with auto-reload
37+
│ │ └── logger.rs # Logging initialization
38+
│ └── lua_engine.rs # Lua engine integration (optional)
39+
├── examples/
40+
│ ├── config.example.toml # Simple configuration example
41+
│ └── config.example_full.toml # Complete configuration example
42+
├── docs/ # Documentation (Docusaurus site)
43+
├── assets/ # Static assets (logo, etc.)
44+
├── Cargo.toml # Cargo manifest with dependencies
45+
├── Cargo.lock # Cargo lock file
46+
├── Makefile # Build and development commands
47+
├── Dockerfile # Docker container configuration
48+
├── README.md # Chinese documentation
49+
├── README_en.md # English documentation
50+
└── AGENTS.md # This handover document
51+
```
52+
53+
## Core Architecture
54+
55+
### Main Entry Point (`src/main.rs`)
56+
57+
The server starts by:
58+
59+
1. Parsing command-line arguments
60+
2. Loading and validating configuration
61+
3. Initializing logging
62+
4. Starting initial servers based on config
63+
5. Starting config file watcher for auto-reload
64+
6. Handling shutdown signals
65+
66+
Key features:
67+
68+
- Uses Tokio async runtime
69+
- Uses mimalloc as global allocator for better performance
70+
- Configuration watcher with auto-reload on file change
71+
- Graceful shutdown handling
72+
73+
### Configuration System (`src/config.rs`)
74+
75+
The configuration system uses TOML format and supports:
76+
77+
- Global settings: log level, log folder
78+
- Multiple virtual hosts with separate configurations
79+
- Per-host routes with:
80+
- Static file serving
81+
- Reverse proxying
82+
- Lua scripting
83+
- HTTP redirects
84+
- SSL/TLS configuration
85+
- Timeout settings
86+
87+
Key types:
88+
89+
- `Settings`: Root configuration struct
90+
- `SettingHost`: Virtual host configuration
91+
- `SettingRoute`: Individual route configuration (static/proxy/lua/redirect)
92+
93+
Validation:
94+
95+
- SSL certificate/key existence check
96+
- Route location format validation
97+
- Required fields validation
98+
- File path validation
99+
100+
### HTTP Server (`src/http/mod.rs`)
101+
102+
The HTTP server uses Axum framework and axum-server for:
103+
104+
- Route registration and matching
105+
- Virtual host support
106+
- HTTPS with Rustls
107+
- HTTP/2 support
108+
- Timeout handling
109+
- Compression
110+
- Middleware chain (version header, custom headers, logging)
111+
112+
Key features:
113+
114+
- Route matching with optional trailing slash support
115+
- Wildcard path handling for static files
116+
- Per-route body size limits
117+
- Host configuration stored in global `HOSTS` map (DashMap for concurrency)
118+
119+
### Configuration Watcher (`src/utils/config_watcher.rs`)
120+
121+
The config watcher uses the `notify` crate to monitor file changes with:
122+
123+
- Debounce mechanism to avoid frequent reloads
124+
- Retry logic for failed config reads
125+
- Re-watch logic for renamed/deleted files
126+
- Async channel communication
127+
- Graceful shutdown handling
128+
129+
Configuration options:
130+
131+
- `debounce_ms`: Debounce time for events (default: 500ms)
132+
- `rewatch_delay_ms`: Delay after rename/delete events (default: 800ms)
133+
- `max_retries`: Max retries for config read (default: 5)
134+
- `retry_delay_ms`: Delay between retries (default: 100ms)
12135

13136
## Build and Test Commands
14137

@@ -78,6 +201,7 @@ make loongarch # LoongArch Linux
78201
## Code Style Guidelines
79202

80203
### General
204+
81205
- **File encoding**: UTF-8
82206
- **Line endings**: LF (Unix-style)
83207
- **Trailing whitespace**: Must be trimmed
@@ -87,9 +211,11 @@ make loongarch # LoongArch Linux
87211
### Rust-specific
88212

89213
#### Import Order
90-
1. Standard library (std::*)
214+
215+
1. Standard library (std::\*)
91216
2. External dependencies (alphabetical)
92-
3. Internal modules (crate::*, super::*, self::*)
217+
3. Internal modules (crate::_, super::_, self::\*)
218+
93219
```rust
94220
// Good import example
95221
use std::path::Path;
@@ -99,18 +225,21 @@ use crate::config::Settings;
99225
```
100226

101227
#### Naming Conventions
228+
102229
- Variables/functions: `snake_case`
103230
- Types/traits/enums: `PascalCase`
104231
- Constants: `SCREAMING_SNAKE_CASE`
105232
- Modules: `snake_case`
106233
- Lifetimes: `'a`, `'b` (single lowercase)
107234

108235
#### Type Annotations
236+
109237
- Use inference for local variables
110238
- Explicit types for:
111239
- Public API signatures
112240
- Complex type contexts
113241
- Where inference is ambiguous
242+
114243
```rust
115244
// Good type annotation
116245
pub fn load_config(path: &Path) -> anyhow::Result<Settings> {
@@ -120,17 +249,21 @@ pub fn load_config(path: &Path) -> anyhow::Result<Settings> {
120249
```
121250

122251
#### Error Handling
252+
123253
- Use `anyhow::Result` for app errors
124254
- Use `thiserror::Error` for structured errors
125255
- Always use `?` operator instead of `unwrap()`/`expect()`
126256
- Add context with `with_context()`:
257+
127258
```rust
128259
std::fs::read(path).with_context(|| format!("Failed to read {path:?}"))?;
129260
```
130261

131262
### Memory Safety
263+
132264
- Prefer safe Rust constructs
133265
- Document unsafe blocks:
266+
134267
```rust
135268
// SAFETY: Buffer size verified before access
136269
unsafe { *ptr = value; }
@@ -139,12 +272,14 @@ unsafe { *ptr = value; }
139272
## Documentation Guidelines
140273

141274
### Code Comments
275+
142276
- `///` for public API documentation
143277
- `//!` for module-level documentation
144278
- `//` for implementation comments
145279

146280
### Examples
147-
```rust
281+
282+
````rust
148283
/// Validates configuration settings
149284
///
150285
/// # Examples
@@ -156,13 +291,15 @@ unsafe { *ptr = value; }
156291
pub fn validate(&self) -> anyhow::Result<()> {
157292
// ...
158293
}
159-
```
294+
````
160295

161296
### Error Messages
297+
162298
- Include actionable information
163299
- Suggest solutions when possible
164300

165301
## Security Best Practices
302+
166303
- Never log secrets or credentials
167304
- Validate all external inputs
168305
- Use constant-time comparisons for sensitive data
@@ -188,15 +325,16 @@ cargo run -- --config path/to/config.toml
188325

189326
## Key Modules
190327

191-
- `src/main.rs`: Entry point
192-
- `src/config.rs`: Configuration loading
193-
- `src/http/mod.rs`: Axum server
194-
- `src/utils/config_watcher.rs`: Config reloading
195-
- `src/lua_engine.rs`: Lua integration
328+
- `src/main.rs`: Entry point and server lifecycle management
329+
- `src/config.rs`: Configuration loading, validation, and struct definitions
330+
- `src/http/mod.rs`: Axum server creation and route registration
331+
- `src/utils/config_watcher.rs`: Config reloading on file change
332+
- `src/lua_engine.rs`: Lua integration (optional feature)
196333

197334
## Performance Optimization
198335

199336
Release profile:
337+
200338
```toml
201339
[profile.release]
202340
opt-level = 3
@@ -209,8 +347,121 @@ codegen-units = 1
209347
## Git Integration
210348

211349
- Branch: `<type>/<short-description>` (feat|fix|docs|refactor|test|chore)
212-
- Commits:
350+
- Commits:
213351
- Imperative mood ("Add", "Fix", "Update")
214352
- First line ≤ 50 chars
215353
- Explain "why" in body
216-
- Never commit: Secrets, credentials, `.env` files
354+
- Never commit: Secrets, credentials, `.env` files
355+
356+
## Dependencies Overview
357+
358+
| Dependency | Version | Purpose |
359+
| ----------- | ------- | ----------------------------------- |
360+
| axum | 0.8.8 | Web framework |
361+
| axum-server | 0.8.0 | HTTP server implementation with TLS |
362+
| hyper | 1.8.1 | HTTP client/server core |
363+
| dashmap | 6.1.0 | Concurrent hash map |
364+
| notify | 8.2.0 | File system watching |
365+
| mlua | 0.11.5 | Lua integration (optional) |
366+
| mimalloc | 0.1.48 | Memory allocator |
367+
| tracing | 0.1.44 | Logging system |
368+
| toml | 0.9.11 | TOML parsing |
369+
370+
## Configuration Example
371+
372+
```toml
373+
log_level = "debug"
374+
log_folder = "./logs"
375+
376+
[[host]]
377+
ip = "127.0.0.1"
378+
port = 8080
379+
ssl = false
380+
timeout = 60
381+
server_name = "localhost"
382+
383+
[[host.route]]
384+
location = "/"
385+
root = "./public"
386+
index = ["index.html", "index.htm"]
387+
auto_index = true
388+
389+
[[host.route]]
390+
location = "/api"
391+
proxy_pass = "http://localhost:3000"
392+
proxy_timeout = 30
393+
max_body_size = 1048576
394+
395+
[[host]]
396+
ip = "0.0.0.0"
397+
port = 443
398+
ssl = true
399+
certificate = "./cert.pem"
400+
certificate_key = "./key.pem"
401+
timeout = 30
402+
403+
[[host.route]]
404+
location = "/"
405+
root = "./ssl_public"
406+
error_page = { status = 404, page = "/404.html" }
407+
```
408+
409+
## Common Tasks
410+
411+
### Adding a New Feature
412+
413+
1. Create a new branch: `git checkout -b feat/your-feature`
414+
2. Implement the feature
415+
3. Add tests in the appropriate module
416+
4. Run tests: `cargo test`
417+
5. Run lint: `cargo clippy`
418+
6. Format code: `cargo fmt`
419+
7. Commit changes
420+
8. Create PR
421+
422+
### Debugging
423+
424+
- Run in debug mode with logging: `cargo run -- --config path/to/config.toml`
425+
- View detailed logs: Set `log_level = "trace"` in config
426+
- Use `cargo test -- --nocapture` to see stdout in tests
427+
428+
### Performance Profiling
429+
430+
- Build with profiling: `cargo build --release --features flame`
431+
- Use flamegraphs: `cargo flamegraph`
432+
- Check memory usage with Valgrind: `valgrind --tool=massif target/release/candy`
433+
434+
## Troubleshooting
435+
436+
### Common Issues
437+
438+
1. **Configuration errors**: Check that all required fields are present and valid
439+
2. **Port already in use**: Change port in config or kill existing process
440+
3. **SSL certificate errors**: Verify certificate and key paths are correct
441+
4. **Static file not found**: Check root path and file permissions
442+
5. **Config reload not working**: Ensure watcher has read permissions on config file
443+
444+
## Handover Notes
445+
446+
Key areas to focus on:
447+
448+
- Configuration validation logic in `src/config.rs`
449+
- Route matching and host selection in `src/http/mod.rs`
450+
- Config watcher implementation in `src/utils/config_watcher.rs`
451+
- Lua integration in `src/lua_engine.rs` and `src/http/lua/`
452+
- Middleware chain in `src/middlewares/`
453+
454+
Current known limitations:
455+
456+
- No support for WebSocket proxying (planned)
457+
- Limited Lua API (can be extended)
458+
- No built-in caching mechanism
459+
460+
Future roadmap:
461+
462+
- WebSocket support
463+
- Advanced routing rules
464+
- Caching middleware
465+
- Prometheus metrics
466+
- Health check endpoints
467+

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ reqwest = { version = "0.13.1", default-features = false, features = [
4343
"rustls",
4444
"stream",
4545
"system-proxy",
46-
# "native-tls-vendored",
4746
"zstd",
4847
] }
4948
serde = { version = "1.0.228", features = ["derive"] }

0 commit comments

Comments
 (0)