Add body_limit middleware that reads limit from ArcSwap<DynamicConfig>
on each request, enabling runtime config changes without restart.
Uses Content-Length header check for fast rejection and http_body_util::Limited
for streaming body enforcement. Default limit: 100 MB (104,857,600 bytes).
Returns 413 Payload Too Large when exceeded.
- Add TokenBucket with nodelay semantics (nginx limit_req burst nodelay)
- Per-IP rate limiting: IPv4 /32, IPv6 /64 prefix normalization
- DashMap for concurrent access, ArcSwap for lock-free config reads
- Background eviction task for stale entry cleanup
- 429 response with plain text body, RATE_LIMIT log prefix
- Config reload adopts new rate/burst on next request without clearing state
- Unit tests for bucket algorithm and IPv6 normalization
- Integration tests for 429 responses and per-IP independence
- Add health.rs module with start_health_check_listener() that binds to
127.0.0.1:{health_check_port} and serves GET /health returning 200 OK
with empty body
- Add health_route() in proxy/handler.rs for HTTPS listener fallback
- Add port conflict detection in config validation: health_check_port
must not conflict with listener ports on 127.0.0.1/localhost/0.0.0.0
- health_check_port = 0 disables the separate listener (handled at call
site)
- Add unit and integration tests for health check functionality
- Add [lib] target to enable integration test imports
- Add rcgen and reqwest dev-dependencies for TLS and HTTP test helpers
- Create src/config/test_fixtures.rs with test_static_config() and test_dynamic_config()
- Create tests/ with integration tests, HTTP test helper (TestUpstream), and TLS test helper (SelfSignedCert)
- Add Clone derives to StaticConfig and related structs for test fixture construction
- All existing tests continue to pass