-
Notifications
You must be signed in to change notification settings - Fork 0
/
rl.go
51 lines (41 loc) · 1.01 KB
/
rl.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
50
51
package ratelimiter
import (
"net/http"
"github.com/urfave/negroni"
)
type limitStrategy interface {
getLimiter(*http.Request) *limiter
}
type rl struct {
opts opts
strategy limitStrategy
}
func newRL(opts opts) negroni.Handler {
l := &rl{opts: opts}
// Decide which limiter func we are going to use depending on the set options
if opts.getKey != nil {
if opts.buckets > 0 && opts.getHasher != nil {
// We want to use buckets and keys limiter
l.strategy = newBucketsAndKeysStrategy(opts)
} else {
// We want to use only keys limiter
l.strategy = newKeysStrategy(opts)
}
} else {
// We want a global limiter
l.strategy = newGlobalStrategy(opts)
}
return l
}
func (m *rl) ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
limiter := m.strategy.getLimiter(req)
ok := limiter.allow()
h := rw.Header()
h.Set("X-RateLimit-Limit", limiter.rpm())
if ok {
next(rw, req)
} else {
h.Set("Retry-After", limiter.retryAfter())
rw.WriteHeader(m.opts.status)
}
}