-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwhitelist_limiter.go
49 lines (43 loc) · 1.17 KB
/
whitelist_limiter.go
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
package ratelimiter
import (
"fmt"
"net"
)
// WhitelistedLimiter wraps a ratelimiter with a whitelist
type WhitelistedLimiter struct {
Limiter Limiter
Whitelist []*net.IPNet
OnWhitelist func(ip string)
}
// ParseWhitelist parses a list of strings as CIDRs
func ParseWhitelist(whitelist []string) ([]*net.IPNet, error) {
wl := make([]*net.IPNet, 0, len(whitelist))
for _, cidr := range whitelist {
_, c, err := net.ParseCIDR(cidr)
if err != nil {
return nil, fmt.Errorf("failed to parse CIDR %q: %w", cidr, err)
}
wl = append(wl, c)
}
return wl, nil
}
// NewWhitelistedLimiter constructs a new WhitelistedLimiter.
func NewWhitelistedLimiter(limiter Limiter, whitelist []*net.IPNet) *WhitelistedLimiter {
return &WhitelistedLimiter{
Limiter: limiter,
Whitelist: whitelist,
}
}
// Limit checks the whitelist for whitelisted IP addresses and then return
// false if any match. If none match then it defers to w.Limiter.Limit
func (w *WhitelistedLimiter) Limit(ip string) bool {
for _, wl := range w.Whitelist {
if wl.Contains(net.ParseIP(ip)) {
if w.OnWhitelist != nil {
w.OnWhitelist(ip)
}
return false
}
}
return w.Limiter.Limit(ip)
}