1package ratelimit_test
2
3import (
4 "fmt"
5 "net"
6 "time"
7
8 "github.com/mjl-/mox/ratelimit"
9)
10
11func ExampleLimiter() {
12 // Make a new rate limit that has maxima per minute, hour and day. The maxima are
13 // tracked per ipmasked1 (ipv4 /32 or ipv6 /64), ipmasked2 (ipv4 /26 or ipv6 /48)
14 // and ipmasked3 (ipv4 /21 or ipv6 /32).
15 //
16 // It is common to allow short bursts (with a narrow window), but not allow a high
17 // sustained rate (with wide window).
18 limit := ratelimit.Limiter{
19 WindowLimits: []ratelimit.WindowLimit{
20 {Window: time.Minute, Limits: [...]int64{2, 3, 4}},
21 {Window: time.Hour, Limits: [...]int64{4, 6, 8}},
22 {Window: 24 * time.Hour, Limits: [...]int64{20, 40, 60}},
23 },
24 }
25
26 tm, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
27
28 fmt.Println("1:", limit.Add(net.ParseIP("127.0.0.1"), tm, 1)) // Success.
29 fmt.Println("2:", limit.Add(net.ParseIP("127.0.0.1"), tm, 1)) // Success.
30 fmt.Println("3:", limit.Add(net.ParseIP("127.0.0.1"), tm, 1)) // Failure, too many from same ip.
31 fmt.Println("4:", limit.Add(net.ParseIP("127.0.0.2"), tm, 1)) // Success, different IP, though nearby.
32 fmt.Println("5:", limit.Add(net.ParseIP("127.0.0.2"), tm, 1)) // Failure, hits ipmasked2 check.
33 fmt.Println("6:", limit.Add(net.ParseIP("127.0.0.1"), tm.Add(time.Minute), 1)) // Success, in next minute.
34 fmt.Println("7:", limit.Add(net.ParseIP("127.0.0.1"), tm.Add(2*time.Minute), 1)) // Success, in another minute.
35 fmt.Println("8:", limit.Add(net.ParseIP("127.0.0.1"), tm.Add(3*time.Minute), 1)) // Failure, hitting hourly window for ipmasked1.
36 limit.Reset(net.ParseIP("127.0.0.1"), tm.Add(3*time.Minute))
37 fmt.Println("9:", limit.Add(net.ParseIP("127.0.0.1"), tm.Add(3*time.Minute), 1)) // Success.
38
39 // Output:
40 // 1: true
41 // 2: true
42 // 3: false
43 // 4: true
44 // 5: false
45 // 6: true
46 // 7: true
47 // 8: false
48 // 9: true
49}
50