1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
use crateNext;
use crate::;
use Arc;
use Duration;
use ;
use Mutex;
use interval;
/// Builtin Rate Limiter Middleware
///
/// This middleware implements a sliding window rate limiter that controls the number
/// of requests clients can make within a specified time period. It's essential for
/// protecting APIs from abuse, preventing DoS attacks, and ensuring fair resource
/// usage across clients. The middleware uses an in-memory store with automatic cleanup
/// and supports both direct connections and proxy environments.
///
/// ## Features
///
/// * **Sliding window algorithm** - More accurate than fixed windows, prevents burst traffic at window boundaries
/// * **Per-client tracking** - Individual rate limits based on client IP addresses
/// * **Proxy support** - Extracts real client IPs from `X-Forwarded-For` headers
/// * **Automatic cleanup** - Periodic cleanup of expired entries to prevent memory leaks
/// * **Standard headers** - Follows RFC-compliant rate limit headers for client guidance
/// * **Configurable responses** - Custom messages and limits for different use cases
/// * **Thread-safe** - Uses async mutexes for safe concurrent access
/// * **Memory efficient** - Lightweight tracking structure per client
/// * **Graceful degradation** - Continues operation even under high load
///
/// ## Rate Limiting Algorithm
///
/// The middleware uses a **sliding window** approach:
/// 1. **First request** from a client starts a new window
/// 2. **Subsequent requests** within the window are counted against the limit
/// 3. **Window expiry** resets the counter and starts a new window
/// 4. **Requests over limit** are rejected with 429 status until window resets
///
/// This approach is more accurate than fixed windows because it doesn't allow
/// burst traffic at window boundaries (e.g., 2x limit by making requests at
/// the end of one window and start of the next).
///
/// ## Client Identification
///
/// ### Direct Connection Mode (`proxy: false`)
/// - Uses the direct client IP address from the TCP connection
/// - Suitable for applications directly facing the internet
/// - Most accurate when clients connect directly
///
/// ### Proxy Mode (`proxy: true`)
/// - Extracts the real client IP from `X-Forwarded-For` header
/// - Falls back to direct IP if header is missing or malformed
/// - Essential when behind load balancers, CDNs, or reverse proxies
/// - Takes the first IP from comma-separated list (closest to client)
///
/// ## Memory Management
///
/// The middleware includes automatic cleanup to prevent memory leaks:
/// * **Cleanup interval**: Every 5 minutes
/// * **Cleanup criteria**: Removes entries older than the configured window
/// * **Background task**: Runs independently without blocking requests
/// * **Memory bounds**: Automatically limits growth of client tracking data
///
/// ## Configuration Options
///
/// * `window_ms` - Duration of the rate limiting window (default: 10 seconds)
/// * `max_requests` - Maximum requests allowed per client per window (default: 10)
/// * `proxy` - Whether to extract real IP from proxy headers (default: false)
/// * `message` - Custom message returned when limit exceeded (default: "Too many requests")
///
/// ## Response Headers
///
/// The middleware adds standard rate limiting headers to all responses:
/// * `X-RateLimit-Limit` - The maximum number of requests allowed in the window
/// * `X-RateLimit-Remaining` - Number of requests remaining in current window
/// * `X-RateLimit-Reset` - Seconds until the current window resets
/// * `Retry-After` - Seconds to wait before retrying (only when rate limited)
///
/// These headers help clients implement proper backoff strategies and respect rate limits.
///
/// ## Examples
///
/// Basic rate limiting with default settings:
///
/// ```no_run
/// use ripress::{app::App, middlewares::rate_limiter::RateLimiterConfig};
///
/// let mut app = App::new();
/// app.use_rate_limiter(Some(RateLimiterConfig::default()));
/// ```
///
/// API rate limiting for production (100 requests per minute):
///
/// ```no_run
/// use ripress::{app::App, middlewares::rate_limiter::RateLimiterConfig};
/// use std::time::Duration;
///
/// let mut app = App::new();
/// let config = RateLimiterConfig {
/// window_ms: Duration::from_secs(60), // 1 minute window
/// max_requests: 100,
/// proxy: true, // Behind load balancer
/// message: "Rate limit exceeded. Please try again later.".to_string(),
/// };
/// app.use_rate_limiter(Some(config));
/// ```
///
/// Strict rate limiting for sensitive endpoints:
///
/// ```no_run
/// use ripress::{app::App, middlewares::rate_limiter::RateLimiterConfig};
/// use std::time::Duration;
///
/// let mut app = App::new();
/// let config = RateLimiterConfig {
/// window_ms: Duration::from_secs(300), // 5 minute window
/// max_requests: 5, // Very restrictive
/// proxy: false,
/// message: "Too many attempts. Please wait before trying again.".to_string(),
/// };
/// app.use_rate_limiter(Some(config));
/// ```
///
/// Development-friendly configuration:
///
/// ```no_run
/// use ripress::{app::App, middlewares::rate_limiter::RateLimiterConfig};
/// use std::time::Duration;
///
/// let mut app = App::new();
/// let config = RateLimiterConfig {
/// window_ms: Duration::from_secs(10),
/// max_requests: 1000, // Very permissive for development
/// proxy: false,
/// message: "Development rate limit exceeded".to_string(),
/// };
/// app.use_rate_limiter(Some(config));
/// ```
///
/// Multiple rate limiters for different endpoints:
///
/// ```no_run
/// use ripress::{app::App, middlewares::rate_limiter::RateLimiterConfig};
/// use std::time::Duration;
///
/// let mut app = App::new();
///
/// // Generous limits for read operations
/// let read_config = RateLimiterConfig {
/// window_ms: Duration::from_secs(60),
/// max_requests: 200,
/// proxy: true,
/// message: "Too many read requests".to_string(),
/// };
/// app.use_rate_limiter(Some(read_config));
///
/// // Stricter limits for write operations
/// let write_config = RateLimiterConfig {
/// window_ms: Duration::from_secs(60),
/// max_requests: 50,
/// proxy: true,
/// message: "Too many write requests".to_string(),
/// };
/// app.use_rate_limiter(Some(write_config));
/// ```
///
/// Using default configuration:
///
/// ```no_run
/// use ripress::app::App;
///
/// let mut app = App::new();
/// app.use_rate_limiter(None); // Uses defaults
/// ```
///
/// ## Client Integration Examples
///
/// ### JavaScript/Fetch API
/// ```javascript
/// async function apiCall(url) {
/// const response = await fetch(url);
///
/// if (response.status === 429) {
/// const retryAfter = response.headers.get('Retry-After');
/// console.log(`Rate limited. Retry after ${retryAfter} seconds`);
/// // Implement exponential backoff
/// await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
/// return apiCall(url); // Retry
/// }
///
/// // Check remaining requests
/// const remaining = response.headers.get('X-RateLimit-Remaining');
/// console.log(`${remaining} requests remaining`);
///
/// return response.json();
/// }
/// ```
///
/// ### curl Example
/// ```bash
/// # Check rate limit headers
/// curl -I https://api.example.com/data
/// # X-RateLimit-Limit: 100
/// # X-RateLimit-Remaining: 95
/// # X-RateLimit-Reset: 45
/// ```
///
/// ## Security Considerations
///
/// ### IP Spoofing Prevention
/// - **Validate proxy headers** when `proxy: true`
/// - **Use trusted proxies** only - validate `X-Forwarded-For` sources
/// - **Consider multiple headers** like `X-Real-IP`, `CF-Connecting-IP`
/// - **Implement IP validation** for critical applications
///
/// ### DDoS Protection
/// - Rate limiting alone may not stop sophisticated DDoS attacks
/// - Consider combining with other protective measures
/// - Monitor for distributed attacks across many IPs
/// - Implement circuit breakers for upstream services
///
/// ### Bypass Attempts
/// - Clients may try to bypass limits by changing IP addresses
/// - Consider session-based or token-based limiting for authenticated users
/// - Monitor for suspicious patterns in rate limit violations
/// - Implement progressive penalties for repeated violations
///
/// ## Performance Characteristics
///
/// ### Memory Usage
/// - **Per-client overhead**: ~32 bytes (IP string + tracking data)
/// - **Cleanup efficiency**: Periodic cleanup prevents unbounded growth
/// - **Hash map operations**: O(1) average case for lookups and updates
/// - **Memory bounds**: Automatically managed through cleanup task
///
/// ### CPU Usage
/// - **Lock contention**: Uses async mutex to minimize blocking
/// - **Cleanup cost**: Background task runs every 5 minutes
/// - **Header parsing**: Minimal overhead for proxy IP extraction
/// - **Time calculations**: Efficient duration-based comparisons
///
/// ### Scalability
/// - **Single-instance**: Suitable for single-server deployments
/// - **Multi-instance**: Each instance maintains separate state
/// - **Redis alternative**: Consider external stores for distributed deployments
/// - **Horizontal scaling**: May need shared rate limit store
///
/// ## Monitoring and Observability
///
/// ### Metrics to Track
/// - Rate limit violations per endpoint
/// - Top rate-limited IP addresses
/// - Average requests per client per window
/// - Memory usage of client tracking data
///
/// ### Logging Considerations
/// - Log rate limit violations for security monitoring
/// - Track cleanup task performance
/// - Monitor for memory leaks or excessive growth
/// - Alert on unusual rate limiting patterns
///
/// ## Limitations
///
/// ### Single Instance State
/// - Rate limits are per-application instance
/// - Load balanced deployments may see inconsistent limits
/// - Consider Redis or database-backed solutions for distributed systems
///
/// ### Memory Constraints
/// - All client data stored in memory
/// - Not suitable for applications with millions of unique clients
/// - Cleanup task may not keep up under extreme load
///
/// ### IP-Based Limitations
/// - NAT/proxy environments may affect multiple users
/// - IPv6 addresses require more memory
/// - Mobile users may change IPs frequently
///
/// ## Best Practices
///
/// ### Configuration Guidelines
/// - Set `window_ms` based on your API's usage patterns
/// - Use generous limits initially and adjust based on monitoring
/// - Enable `proxy: true` when behind load balancers or CDNs
/// - Provide clear error messages to guide client behavior
///
/// ### Production Deployment
/// - Monitor rate limit violation patterns
/// - Implement alerting for excessive rate limiting
/// - Consider progressive rate limiting (increasing penalties)
/// - Test rate limiting behavior under load
///
/// ### Client-Friendly Design
/// - Always include rate limit headers
/// - Provide clear error messages with retry guidance
/// - Document rate limits in API documentation
/// - Implement proper error handling in client applications
/// Configuration struct for the rate limiter middleware
///
/// This struct defines all configurable aspects of the rate limiting behavior,
/// including time windows, request limits, proxy support, and error messaging.
/// The configuration is cloned per request to ensure thread safety.
///
/// ## Configuration Strategy
///
/// Choose configuration values based on your application's needs:
/// - **Public APIs**: More permissive limits with longer windows
/// - **Private APIs**: Moderate limits based on expected usage
/// - **Authentication endpoints**: Very strict limits with longer windows
/// - **File uploads**: Consider request size, not just count
///
/// ## Window vs Limits Trade-offs
///
/// * **Shorter windows + higher limits**: More responsive to traffic bursts
/// * **Longer windows + lower limits**: Better for preventing sustained abuse
/// * **Multiple tiers**: Different limits for different endpoint types
/// Internal structure for tracking client rate limit data
///
/// This lightweight structure stores the minimum information needed
/// to track each client's request count and window timing. The
/// `Copy` trait allows efficient updates without ownership issues.
/// Creates a rate limiter middleware function
///
/// Returns a middleware function that implements sliding window rate limiting
/// based on client IP addresses. The middleware automatically handles window
/// expiration, client tracking, cleanup, and proper HTTP response codes and headers.
///
/// ## Parameters
///
/// * `config` - Optional rate limiter configuration. If `None`, uses `RateLimiterConfig::default()`
/// which allows 10 requests per 10-second window with no proxy support.
///
/// ## Returns
///
/// A middleware function compatible with the ripress framework that:
/// * Tracks request counts per client IP address using sliding windows
/// * Automatically rejects requests exceeding configured limits with 429 status
/// * Adds standard rate limiting headers to all responses
/// * Supports both direct and proxy-based client IP detection
/// * Runs background cleanup to prevent memory leaks
/// * Handles concurrent access safely with async mutexes
///
/// ## Middleware Behavior
///
/// ### For Requests Within Limits
/// 1. Identifies client IP (direct or via proxy headers)
/// 2. Updates request count for the current window
/// 3. Adds rate limiting headers to response
/// 4. Continues to next middleware/handler
///
/// ### For Requests Exceeding Limits
/// 1. Calculates time remaining in current window
/// 2. Returns 429 Too Many Requests status immediately
/// 3. Includes retry guidance in headers and response body
/// 4. Does not call subsequent middleware or handlers
///
/// ## Background Tasks
///
/// The middleware spawns a cleanup task that:
/// * Runs every 5 minutes to remove expired client entries
/// * Prevents memory leaks from accumulating client data
/// * Runs independently without affecting request processing
/// * Uses the same window duration for cleanup timing
///
/// ## Thread Safety and Performance
///
/// * **Async mutex**: Prevents blocking while ensuring data consistency
/// * **Arc sharing**: Efficient sharing of client data across requests
/// * **Minimal locking**: Lock held only for map operations, not entire request
/// * **Background cleanup**: Maintains performance under sustained load
/// * **Copy semantics**: Efficient updates of client tracking data
///
/// ## Memory Management
///
/// * **Automatic cleanup**: Expired entries removed every 5 minutes
/// * **Bounded growth**: Client map size naturally limited by cleanup
/// * **Lightweight entries**: Minimal memory per tracked client
/// * **Efficient operations**: Hash map provides O(1) average lookup/update
///
/// ## Error Handling
///
/// The middleware is designed to be robust and never panic:
/// * **Missing headers**: Gracefully falls back to direct IP
/// * **Invalid durations**: Uses saturating arithmetic to prevent underflow
/// * **Lock contention**: Async mutex prevents deadlocks
/// * **Memory pressure**: Background cleanup prevents unbounded growth
///
/// ## Rate Limiting Headers
///
/// All responses include standard headers for client guidance:
/// * **X-RateLimit-Limit**: Maximum requests allowed in window
/// * **X-RateLimit-Remaining**: Requests remaining in current window
/// * **X-RateLimit-Reset**: Seconds until current window expires
/// * **Retry-After**: Seconds to wait before retrying (429 responses only)
pub + Send + Sync + 'static