Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/.agent/docs_coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
| Links | `recipes/pagination.md` | `rustapi-core/src/hateoas.rs` | OK |
| **Extras** | | | |
| Auth (JWT) | `recipes/jwt_auth.md` | `rustapi-extras/src/jwt` | OK |
| Auth (OAuth2) | `recipes/oauth2_client.md` | `rustapi-extras/src/oauth2` | OK |
| Security | `recipes/csrf_protection.md` | `rustapi-extras/src/security` | OK |
| Observability | `crates/rustapi_extras.md` | `rustapi-extras/src/telemetry` | OK |
| Audit Logging | `recipes/audit_logging.md` | `rustapi-extras/src/audit` | OK |
| Middleware (Advanced) | `recipes/advanced_middleware.md` | `rustapi-extras/src/{rate_limit, dedup, cache}` | OK |
| **Jobs** | | | |
| Job Queue (Crate) | `crates/rustapi_jobs.md` | `rustapi-jobs` | OK |
| Background Jobs (Recipe) | `recipes/background_jobs.md` | `rustapi-jobs` | OK |
Expand Down
3 changes: 3 additions & 0 deletions docs/.agent/docs_inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
| `docs/cookbook/src/getting_started/installation.md` | Installation instructions | Docs | OK |
| `docs/cookbook/src/learning/README.md` | Learning path entry point | Docs | OK |
| `docs/cookbook/src/recipes/*.md` | Specific implementation guides | Docs | OK |
| `docs/cookbook/src/recipes/advanced_middleware.md` | Recipe for Rate Limit, Dedup, Cache | Docs | OK |
| `docs/cookbook/src/recipes/audit_logging.md` | Recipe for Audit Logging | Docs | OK |
| `docs/cookbook/src/recipes/oauth2_client.md` | Recipe for OAuth2 Client | Docs | OK |
| `crates/rustapi-core/src/hateoas.rs` | API Reference for HATEOAS | rustapi-core | OK |
| `crates/rustapi-core/src/extract.rs` | API Reference for Extractors | rustapi-core | OK |
4 changes: 2 additions & 2 deletions docs/.agent/last_run.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"last_processed_ref": "v0.1.335",
"date": "2026-02-15",
"notes": "Fixed critical inaccuracy in SSR recipe. Updated recipes index to be comprehensive. Verified docs coverage."
"date": "2026-02-16",
"notes": "Added recipes for Advanced Middleware, Audit Logging, and OAuth2 Client. Updated Learning Path to include these features."
}
30 changes: 30 additions & 0 deletions docs/.agent/run_report_2026-02-16.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Run Report: 2026-02-16

## Detected Version
- **Ref:** v0.1.335
- **Status:** No version change detected. Running "Continuous Improvement" phase.

## Changes
### Cookbook Improvements
- **New Recipe:** `recipes/advanced_middleware.md`
- Covers Rate Limiting (`RateLimitLayer`), Request Deduplication (`DedupLayer`), and Response Caching (`CacheLayer`).
- **New Recipe:** `recipes/audit_logging.md`
- Covers Audit Events (`AuditEvent`), Actions (`AuditAction`), Compliance (`ComplianceInfo`), and GDPR/SOC2 features.
- **New Recipe:** `recipes/oauth2_client.md`
- Covers OAuth2 Client configuration (`OAuth2Config`) and authorization flow (`OAuth2Client`).

### Learning Path Improvements
- **Curriculum Update:** `learning/curriculum.md`
- Added **Module 8: Advanced Middleware** (Phase 3).
- Added **Module 7: Authentication** expanded to include OAuth2.
- Added **Module 12: Observability & Auditing** (Phase 4).
- Renumbered subsequent modules to maintain sequence.

### Documentation Tracking
- Updated `docs_inventory.md` with new recipe files.
- Updated `docs_coverage.md` to reflect coverage of `rate-limit`, `dedup`, `cache`, `audit`, and `oauth2-client` features in `rustapi-extras`.

## TODOs / Next Steps
- Validate links in new recipes.
- Consider adding a dedicated recipe for "Guard" (RBAC) middleware once the feature stabilizes.
- Verify `rustapi-extras` feature flags in examples against `Cargo.toml`.
3 changes: 3 additions & 0 deletions docs/cookbook/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,20 @@
- [Creating Resources](recipes/crud_resource.md)
- [Pagination & HATEOAS](recipes/pagination.md)
- [JWT Authentication](recipes/jwt_auth.md)
- [OAuth2 Client](recipes/oauth2_client.md)
- [CSRF Protection](recipes/csrf_protection.md)
- [Database Integration](recipes/db_integration.md)
- [Testing & Mocking](recipes/testing.md)
- [File Uploads](recipes/file_uploads.md)
- [Background Jobs](recipes/background_jobs.md)
- [Custom Middleware](recipes/custom_middleware.md)
- [Advanced Middleware](recipes/advanced_middleware.md)
- [Real-time Chat](recipes/websockets.md)
- [Server-Side Rendering (SSR)](recipes/server_side_rendering.md)
- [AI Integration (TOON)](recipes/ai_integration.md)
- [Production Tuning](recipes/high_performance.md)
- [Resilience Patterns](recipes/resilience.md)
- [Audit Logging](recipes/audit_logging.md)
- [Time-Travel Debugging (Replay)](recipes/replay.md)
- [Deployment](recipes/deployment.md)
- [HTTP/3 (QUIC)](recipes/http3_quic.md)
Expand Down
69 changes: 44 additions & 25 deletions docs/cookbook/src/learning/curriculum.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,37 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u

**Goal:** Security, Real-time, and Production readiness.

### Module 7: Authentication (JWT)
### Module 7: Authentication (JWT & OAuth2)
- **Prerequisites:** Phase 2.
- **Reading:** [JWT Auth Recipe](../recipes/jwt_auth.md).
- **Task:** Implement a login route that returns a JWT. Protect user routes with `AuthUser` extractor.
- **Reading:** [JWT Auth Recipe](../recipes/jwt_auth.md), [OAuth2 Client](../recipes/oauth2_client.md).
- **Task:**
1. Implement a login route that returns a JWT.
2. Protect user routes with `AuthUser` extractor.
3. (Optional) Implement "Login with Google" using `OAuth2Client`.
- **Expected Output:** Protected routes return `401 Unauthorized` without a valid token.
- **Pitfalls:** Hardcoding secrets. Not checking token expiration.

#### 🧠 Knowledge Check
1. What is the role of the `AuthUser` extractor?
2. How do you protect a route with JWT?
2. How does OAuth2 PKCE improve security?
3. Where should you store the JWT secret?

### Module 8: WebSockets & Real-time
### Module 8: Advanced Middleware
- **Prerequisites:** Module 7.
- **Reading:** [Advanced Middleware](../recipes/advanced_middleware.md).
- **Task:**
1. Apply `RateLimitLayer` to your login endpoint (10 requests/minute).
2. Add `DedupLayer` to a payment endpoint.
3. Cache the response of a public "stats" endpoint.
- **Expected Output:** Sending 11 login attempts results in `429 Too Many Requests`.
- **Pitfalls:** Caching responses that contain user-specific data.

#### 🧠 Knowledge Check
1. What header indicates when the rate limit resets?
2. Why is request deduplication important for payments?
3. Which requests are typically safe to cache?

### Module 9: WebSockets & Real-time
- **Prerequisites:** Phase 2.
- **Reading:** [WebSockets Recipe](../recipes/websockets.md).
- **Task:** Create a chat endpoint where users can broadcast messages.
Expand All @@ -131,21 +149,21 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
2. Can you share state between HTTP handlers and WebSocket handlers?
3. What happens if a WebSocket handler panics?

### Module 9: Production Readiness & Deployment
### Module 10: Production Readiness & Deployment
- **Prerequisites:** Phase 3.
- **Reading:** [Production Tuning](../recipes/high_performance.md), [Resilience](../recipes/resilience.md), [Deployment](../recipes/deployment.md).
- **Task:**
1. Add `RateLimitLayer`, `CompressionLayer`, and `TimeoutLayer`.
1. Add `CompressionLayer`, and `TimeoutLayer`.
2. Use `cargo rustapi deploy docker` to generate a Dockerfile.
- **Expected Output:** A resilient API ready for deployment.
- **Pitfalls:** Setting timeouts too low for slow operations.

#### 🧠 Knowledge Check
1. Why is rate limiting important?
1. Why is timeout middleware important?
2. What command generates a production Dockerfile?
3. How do you enable compression for responses?

### Module 10: Background Jobs & Testing
### Module 11: Background Jobs & Testing
- **Prerequisites:** Phase 3.
- **Reading:** [Background Jobs Recipe](../recipes/background_jobs.md), [Testing Strategy](../concepts/testing.md).
- **Task:**
Expand All @@ -162,7 +180,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
### 🏆 Phase 3 Capstone: "The Real-Time Collaboration Tool"
**Objective:** Build a real-time collaborative note-taking app.
**Requirements:**
- **Auth:** Users must log in to edit notes.
- **Auth:** Users must log in (JWT or OAuth2) to edit notes.
- **Real-time:** Changes to a note are broadcast to all viewers via WebSockets.
- **Jobs:** When a note is deleted, schedule a background job to archive it (simulate archive).
- **Resilience:** Rate limit API requests to prevent abuse.
Expand All @@ -174,22 +192,22 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u

**Goal:** Build observable, resilient, and high-performance distributed systems.

### Module 11: Observability
### Module 12: Observability & Auditing
- **Prerequisites:** Phase 3.
- **Reading:** [Observability (Extras)](../crates/rustapi_extras.md#observability), [Structured Logging](../crates/rustapi_extras.md#structured-logging).
- **Reading:** [Observability (Extras)](../crates/rustapi_extras.md#observability), [Audit Logging](../recipes/audit_logging.md).
- **Task:**
1. Enable `structured-logging` and `otel` features.
2. Configure tracing to export spans to Jaeger (or console for dev).
3. Add custom metrics for "active_users" and "jobs_processed".
- **Expected Output:** Logs are JSON formatted with trace IDs. Metrics endpoint exposes Prometheus data.
- **Pitfalls:** High cardinality in metric labels (e.g., using user IDs as labels).
1. Enable `structured-logging` and `otel`.
2. Configure tracing to export spans.
3. Implement `AuditStore` and log a "User Login" event with IP address.
- **Expected Output:** Logs are JSON formatted. Audit log contains a new entry for every login.
- **Pitfalls:** High cardinality in metric labels.

#### 🧠 Knowledge Check
1. What is the difference between logging and tracing?
2. How do you correlate logs across microservices?
3. What is the standard format for structured logs in RustAPI?
1. What is the difference between logging and auditing?
2. Which fields are required in an `AuditEvent`?
3. How does structured logging aid debugging?

### Module 12: Resilience & Security
### Module 13: Resilience & Security
- **Prerequisites:** Phase 3.
- **Reading:** [Resilience Patterns](../recipes/resilience.md), [Time-Travel Debugging](../recipes/replay.md).
- **Task:**
Expand All @@ -204,7 +222,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
2. Why is jitter important in retry strategies?
3. How does Time-Travel Debugging help with "Heisenbugs"?

### Module 13: High Performance
### Module 14: High Performance
- **Prerequisites:** Phase 3.
- **Reading:** [HTTP/3 (QUIC)](../recipes/http3_quic.md), [Performance Tuning](../recipes/high_performance.md).
- **Task:**
Expand All @@ -226,6 +244,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
- **Processing:** Push events to a `rustapi-jobs` queue (Redis backend).
- **Storage:** Workers process events and store aggregates in a database.
- **Observability:** Full tracing from ingestion to storage.
- **Audit:** Log all configuration changes to the system.
- **Resilience:** Circuit breakers on database writes.
- **Testing:** Load test the ingestion endpoint (e.g., with k6 or similar) and observe metrics.

Expand All @@ -235,7 +254,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u

**Goal:** Master integration with AI, gRPC, and server-side rendering.

### Module 14: Server-Side Rendering (SSR)
### Module 15: Server-Side Rendering (SSR)
- **Prerequisites:** Phase 2.
- **Reading:** [SSR Recipe](../recipes/server_side_rendering.md).
- **Task:** Create a dashboard showing system status using `rustapi-view`.
Expand All @@ -247,7 +266,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
2. How do you pass data to a template?
3. How does template reloading work in debug mode?

### Module 15: gRPC Microservices
### Module 16: gRPC Microservices
- **Prerequisites:** Phase 3.
- **Reading:** [gRPC Recipe](../recipes/grpc_integration.md).
- **Task:** Run a gRPC service alongside your HTTP API that handles internal user lookups.
Expand All @@ -259,7 +278,7 @@ This curriculum is designed to take you from a RustAPI beginner to an advanced u
2. Can HTTP and gRPC share the same Tokio runtime?
3. Why might you want to run both in the same process?

### Module 16: AI Integration (TOON)
### Module 17: AI Integration (TOON)
- **Prerequisites:** Phase 2.
- **Reading:** [AI Integration Recipe](../recipes/ai_integration.md).
- **Task:** Create an endpoint that returns standard JSON for browsers but TOON for `Accept: application/toon`.
Expand Down
125 changes: 125 additions & 0 deletions docs/cookbook/src/recipes/advanced_middleware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Advanced Middleware: Rate Limiting, Caching, and Deduplication

As your API grows, you'll need to protect it from abuse and optimize performance. RustAPI provides a suite of advanced middleware in `rustapi-extras` to handle these concerns efficiently.

These patterns are essential for the "Enterprise Platform" learning path and high-traffic services.

## Prerequisites

Add the `rustapi-extras` crate with the necessary features to your `Cargo.toml`.

```toml
[dependencies]
rustapi-rs = { version = "0.1.335", features = ["full"] }
# OR cherry-pick features
# rustapi-extras = { version = "0.1.335", features = ["rate-limit", "dedup", "cache"] }
```

## Rate Limiting

Rate limiting protects your API from being overwhelmed by too many requests from a single client. It uses a "Token Bucket" or "Fixed Window" algorithm to enforce limits.

### How it works
The `RateLimitLayer` tracks request counts per IP address. When a limit is exceeded, it returns `429 Too Many Requests` with a `Retry-After` header.

### Usage

```rust
use rustapi_rs::prelude::*;
use rustapi_extras::rate_limit::RateLimitLayer;
use std::time::Duration;

fn main() {
let app = RustApi::new()
.layer(
RateLimitLayer::new(100, Duration::from_secs(60)) // 100 requests per minute
)
.route("/", get(handler));

// ... run app
}
```

The middleware automatically adds standard headers to responses:
- `X-RateLimit-Limit`: The maximum number of requests allowed.
- `X-RateLimit-Remaining`: The number of requests remaining in the current window.
- `X-RateLimit-Reset`: The timestamp when the window resets.

## Request Deduplication

In distributed systems, clients may retry requests that have already been processed (e.g., due to network timeouts). Deduplication ensures that non-idempotent operations (like payments) are processed only once.

### How it works
The `DedupLayer` checks for an `Idempotency-Key` header. If a request with the same key is seen within the TTL window, it returns `409 Conflict`.

### Usage

```rust
use rustapi_rs::prelude::*;
use rustapi_extras::dedup::DedupLayer;
use std::time::Duration;

fn main() {
let app = RustApi::new()
.layer(
DedupLayer::new()
.header_name("X-Idempotency-Key") // Optional: Custom header name
.ttl(Duration::from_secs(300)) // 5 minutes TTL
)
.route("/payments", post(payment_handler));

// ... run app
}
```

Clients should generate a unique UUID for each operation and send it in the `Idempotency-Key` header.

## Response Caching

Caching can significantly reduce load on your servers by serving stored responses for identical requests.

### How it works
The `CacheLayer` stores successful responses in memory based on the request method and URI. Subsequent requests are served from the cache until the TTL expires.

### Usage

```rust
use rustapi_rs::prelude::*;
use rustapi_extras::cache::CacheLayer;
use std::time::Duration;

fn main() {
let app = RustApi::new()
.layer(
CacheLayer::new()
.ttl(Duration::from_secs(60)) // Cache for 60 seconds
.add_method("GET") // Cache GET requests
.add_method("HEAD") // Cache HEAD requests
)
.route("/heavy-computation", get(heavy_handler));

// ... run app
}
```

Cached responses include an `X-Cache: HIT` header. Original responses have `X-Cache: MISS`.

## Combining Middleware

You can combine these layers to create a robust defense-in-depth strategy.

```rust
let app = RustApi::new()
// 1. Rate Limit (Outer): Reject excessive traffic first
.layer(RateLimitLayer::new(1000, Duration::from_secs(60)))

// 2. Deduplication: Prevent double-processing
.layer(DedupLayer::new())

// 3. Cache: Serve static/computed content quickly
.layer(CacheLayer::new().ttl(Duration::from_secs(30)))

.route("/", get(handler));
```

> **Note**: Order matters! Placing Rate Limit first saves resources by rejecting requests before they hit the cache or application logic.
Loading
Loading