-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rate limit only on failed requests. #24
Comments
Hi @chance-schultz, This is an interesting feature request! The current However I can imagine you could write a custom middleware that manipulates the limits after the handler is run and HTTP status is known. Pseudo-code (not tested / might not compile): rateLimiter := httprate.NewRateLimiter(1000, time.Minute, httprate.WithKeyFuncs(httprate.KeyByIP))
r := chi.NewRouter()
r.Use(rateLimiter.Handler)
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
next.ServeHTTP(ww, r)
if ww.Status() >= 200 && ww.Status < 400 {
key := httprate.KeyByRealIP(r)
currentWindow := time.Now().UTC().Truncate(time.Minute)
rateLimiter.Counter().IncrementBy(key, currentWindow, -1) // Put back
}
})
}) |
@VojtechVitek in your example imagine you set rate limiter to 5 requests per 1 minute. |
@kamilzzz Yes, you're right. You'd need to explicitly check and increment the Pseudo code: rateLimiter := httprate.NewRateLimiter(5, time.Minute, httprate.WithKeyFuncs(httprate.KeyByIP))
r := chi.NewRouter()
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := httprate.KeyByRealIP(r)
currentWindow := time.Now().UTC().Truncate(time.Minute)
previousWindow := currentWindow.Add(-time.Minute)
prev, next, _ := rateLimiter.Counter().Get(key, currentWindow, previousWindow)
// check if rate-limited and return HTTP 429
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
next.ServeHTTP(ww, r)
if ww.Status() == 400 {
rateLimiter.Counter().IncrementBy(key, currentWindow, 1) // Rate-limit requests with wrong payload
}
})
}) |
Is there an easy way to use the existing httprate functionality but push it to the end resolution of the request/response chain instead of at the beginning.
We want to create a couple of open ended mutation endpoints that could be used maliciously so we want to limit the total number of bad requests in a short period of time, but not limit penalize a user who is submitted good data that returns 2XX responses.
The text was updated successfully, but these errors were encountered: