Rust Request Cache Development
Development guidance for working with the `request_cache` Rust library - a caching layer for HTTP requests using SQLite persistence.
Common Development Commands
When working with this library, use these standard Rust commands:
```bash
Build the library
cargo build
Run all tests
cargo test
Run a specific test
cargo test test_cached_request
Generate and open documentation
cargo doc --open
Check code without building (fast feedback)
cargo check
Format code
cargo fmt
Run clippy for linting
cargo clippy
```
Library Architecture
This is a Rust library that wraps `reqwest` to add automatic HTTP request caching capabilities using SQLite as the persistence layer. The design emphasizes type safety, comprehensive error handling, and performance optimization.
Core Components
**Main APIs:**
`cached_request()` - Standalone function that manages its own database connection (returns `Result<Record, RequestCacheError>`)`request()` - Uses an explicit database connection for more control (returns `Result<Record, RequestCacheError>`)`create_connection()` - Creates and initializes a SQLite database connection (returns `Result<Client, RequestCacheError>`)`RequestBuilder` - Modern builder pattern for configuring requests with method chaining (recommended approach)**Data Structures:**
`Record` - Represents a cached HTTP response with metadata (uses `Url` and `HttpMethod` types for type safety)`RequestCacheError` - Comprehensive error type covering database, HTTP, validation, and parsing errors`HttpMethod` - Enum for supported HTTP methods (GET, POST, PUT, DELETE, HEAD, PATCH)**Database Layer:**
Uses `async-sqlite` for asynchronous SQLite operationsOptimized schema with proper indexes: `idx_request_method_expires` for fast lookupsAutomatic table and index creation on connection initializationCache expiration based on Unix timestamps with proper validationCaching Behavior
Responses are cached by URL + HTTP method combinationCache entries have configurable expiration times with validation (must be positive)`force_refresh` parameter bypasses cache and makes fresh requestsOld cache entries for the same URL/method are automatically replacedCache hits are marked with `cached: Some(true)`, misses with `cached: Some(false)`HTTP client is reused across requests for better performanceRequest timeouts are capped at 5 minutes for safetyError Handling & Security Principles
This library follows strict safety and quality standards:
**No `.unwrap()` calls** - all errors are properly handled and propagated using `Result` types**Input validation** - URLs, timeouts, HTTP methods, and database paths are validated before use**Request timeouts** - configurable with sensible defaults and enforced upper limits**Type safety** - uses proper types (`Url`, `HttpMethod` enums) instead of strings**Comprehensive error types** - detailed error information for debugging and recoveryAPI Usage Examples
**Builder Pattern (Recommended):**
```rust
let record = RequestBuilder::new()
.url("https://api.example.com/data")?
.method(HttpMethod::GET)
.timeout(300)?
.user_agent("my-app/1.0")
.database_path("cache.db")
.send()
.await?;
```
**Traditional API:**
```rust
let record = cached_request(
"https://api.example.com/data".to_string(),
"GET".to_string(),
300,
Some(false),
Some("my-app/1.0".to_string()),
Some("cache.db".to_string())
).await?;
```
Testing Structure
Tests use Tokio runtime and follow these patterns:
`TestCleanup` struct with `Drop` implementation for automatic database file cleanup after testsComprehensive error handling tests covering all validation scenariosBuilder pattern functionality tests to ensure API ergonomicsPerformance and caching behavior verification testsTimeout tests use appropriate delays to verify cache expiration logicWhen writing new tests, always ensure proper cleanup of test database files and verify both success and error cases.
Development Guidelines
1. **Always handle errors properly** - use `?` operator or explicit matching, never `.unwrap()`
2. **Validate inputs** - check URLs, timeouts, paths before processing
3. **Use type-safe APIs** - prefer enums and wrapper types over raw strings
4. **Write tests with cleanup** - use `TestCleanup` pattern for database files
5. **Document public APIs** - include examples in doc comments
6. **Run clippy before committing** - address all warnings
7. **Keep performance in mind** - reuse HTTP clients, optimize database queries