demo/
demo.rs

1/* examples/demo.rs */
2
3use lazy_limit::*;
4use std::time::Duration as StdDuration;
5use tokio::time::sleep;
6
7async fn test_basic_limit() {
8    let ip = "1.1.1.1";
9    println!("  Testing IP: {}", ip);
10    println!("  Global rule: 5 req/s. Should allow 5, then deny 6th.");
11
12    for i in 1..=7 {
13        let allowed = limit!(ip, "/some/path").await;
14        println!(
15            "  Request #{}: {}",
16            i,
17            if allowed { "Allowed" } else { "Denied" }
18        );
19        assert_eq!(allowed, i <= 5);
20    }
21
22    println!("  Waiting for 1 second...");
23    sleep(StdDuration::from_secs(1)).await;
24
25    let allowed = limit!(ip, "/some/path").await;
26    println!(
27        "  Request #8 after 1s: {}",
28        if allowed { "Allowed" } else { "Denied" }
29    );
30    assert!(allowed);
31    println!("  Basic test passed.");
32}
33
34async fn test_route_specific() {
35    let ip = "2.2.2.2";
36    println!("  Testing IP: {}", ip);
37    println!("  Global rule: 5 req/s. Route /api/public rule: 10 req/s.");
38    println!("  Effective limit for /api/public is min(5, 10) = 5 req/s.");
39
40    for i in 1..=6 {
41        let allowed = limit!(ip, "/api/public").await;
42        println!(
43            "  Request #{} to /api/public: {}",
44            i,
45            if allowed { "Allowed" } else { "Denied" }
46        );
47        assert_eq!(allowed, i <= 5);
48    }
49
50    println!("  Global limit for {} should now be reached.", ip);
51    let allowed = limit!(ip, "/another/path").await;
52    println!(
53        "  Request to /another/path: {}",
54        if allowed { "Allowed" } else { "Denied" }
55    );
56    assert!(!allowed);
57
58    println!("  Route-specific test passed.");
59}
60
61async fn test_override_mode() {
62    let ip = "3.3.3.3";
63    println!("  Testing IP: {}", ip);
64    println!("  Global rule: 5 req/s. Route /api/premium rule: 20 req/s.");
65    println!("  Using override mode on /api/premium, should allow 20 requests.");
66
67    for i in 1..=21 {
68        let allowed = limit_override!(ip, "/api/premium").await;
69        if i <= 20 {
70            assert!(allowed);
71        } else {
72            println!("  Request #{}: Denied (as expected)", i);
73            assert!(!allowed);
74        }
75    }
76    println!("  Override test passed.");
77}
78
79async fn test_multiple_users() {
80    let ip1 = "4.4.4.4";
81    let ip2 = "5.5.5.5";
82    println!("  Testing with two IPs: {} and {}", ip1, ip2);
83    println!("  Global rule: 5 req/s. Each IP has its own limit.");
84
85    for i in 1..=5 {
86        assert!(
87            limit!(ip1, "/multi").await,
88            "IP1 req {} should be allowed",
89            i
90        );
91        assert!(
92            limit!(ip2, "/multi").await,
93            "IP2 req {} should be allowed",
94            i
95        );
96    }
97
98    println!("  Both IPs have used their 5 requests.");
99    assert!(!limit!(ip1, "/multi").await, "IP1 should now be denied");
100    assert!(!limit!(ip2, "/multi").await, "IP2 should now be denied");
101    println!("  Multiple users test passed.");
102}
103
104async fn test_long_interval() {
105    let ip = "6.6.6.6";
106    println!("  Testing IP: {}", ip);
107    println!("  Route /api/login rule: 3 req/min.");
108
109    println!("  Making 3 requests to /api/login...");
110    assert!(limit!(ip, "/api/login").await);
111    sleep(StdDuration::from_millis(100)).await;
112    assert!(limit!(ip, "/api/login").await);
113    sleep(StdDuration::from_millis(100)).await;
114    assert!(limit!(ip, "/api/login").await);
115
116    println!("  Making 4th request, should be denied by route rule.");
117    assert!(!limit!(ip, "/api/login").await);
118
119    println!("  Checking global limit for {}...", ip);
120    assert!(limit!(ip, "/global-check").await); // 4th global req
121    assert!(limit!(ip, "/global-check").await); // 5th global req
122    assert!(
123        !limit!(ip, "/global-check").await,
124        "6th global req should be denied"
125    );
126
127    println!("  Long interval test passed.");
128}
129
130#[tokio::main]
131async fn main() {
132    println!("Starting lazy-limit demo...\n");
133
134    init_rate_limiter!(
135        default: RuleConfig::new(Duration::seconds(1), 5),
136        max_memory: Some(64 * 1024 * 1024),
137        routes: [
138            ("/api/login", RuleConfig::new(Duration::minutes(1), 3)),
139            ("/api/public", RuleConfig::new(Duration::seconds(1), 10)),
140            ("/api/premium", RuleConfig::new(Duration::seconds(1), 20)),
141        ]
142    )
143    .await;
144
145    println!("Rate limiter initialized with rules:");
146    println!("  - Global: 5 requests/second");
147    println!("  - /api/login: 3 requests/minute");
148    println!("  - /api/public: 10 requests/second");
149    println!("  - /api/premium: 20 requests/second");
150    println!();
151
152    println!("--- Test 1: Basic Global Rate Limiting ---");
153    test_basic_limit().await;
154    println!();
155
156    println!("--- Test 2: Route-Specific Rules (with Global Limit) ---");
157    test_route_specific().await;
158    println!();
159
160    println!("--- Test 3: Override Mode ---");
161    test_override_mode().await;
162    println!();
163
164    println!("--- Test 4: Multiple Users ---");
165    test_multiple_users().await;
166    println!();
167
168    println!("--- Test 5: Long Interval Rules ---");
169    test_long_interval().await;
170    println!();
171
172    println!("All demo tests completed.");
173}