This is a negroni middleware that offers request rate limiting using token bucket approach.
It can apply a global rate limit or per key (where you can specify how to obtain the key from the request).
Additionally you can apply a different rate limit per key.
To add a global rate limit across all your request with a rate of 1 request per second.
m := NewGlobal().
WithDefaultQuota(1, time.Second).
Middleware()
n := negroni.Classic(m)
ts := httptest.NewServer(n)
defer ts.Close()
By default the status code 429 Too Many Requests
will be returned when the specified rate limit is exceeded. In you want to change this behavior and return a different status code, just do:
m := NewGlobal().
WithDefaultQuota(1, time.Second).
WithStatusCode(400).
Middleware()
In this case instead of the 429
, a 400 Bad Request
will be returned.
Sometimes you want to apply a different rate for different kind of request. Lets take as an example that an account_id is being passed as a query parameter, and we want to apply the limit of 1 request per second
but for each account individually instead of globally. In this case you can achieve it by doing:
getKey := func(req *http.Request) string {
return req.URL.Query().Get("account_id")
}
m := NewLimitByKeys(getKey).
WithDefaultQuota(1, time.Second).
Middleware()
...
Using the same example as previously, you can additionally specify a different rate limit for different accounts.
getKey := func(req *http.Request) string {
return req.URL.Query().Get("account_id")
}
getQuota := func(key string) Quota {
if key == "2" {
return NewQuota(1, time.Minute)
}
return NewQuota(2, time.Second)
}
m := NewLimitByKeys(getKey).
WithQuotaByKeys(getQuota).
Middleware()
...
This middleware will return the following headers:
X-RateLimit-Limit
With the set request limit in RPM (taking in account if you specified a key and different quotas per key)Retry-After
With the time in seconds the client should wait until he can issue another request. This is only sent if the limit has been reached