Enforcing a global rate limit.

This commit is contained in:
Maxime Delporte
2025-11-16 10:36:36 +01:00
parent e93375d441
commit 8b0c51123f
5 changed files with 27 additions and 1 deletions

View File

@@ -61,3 +61,8 @@ func (app *application) editConflictResponse(w http.ResponseWriter, r *http.Requ
message := "unable to update the record due to an edit conflict, please try again"
app.errorResponse(w, r, http.StatusConflict, message)
}
func (app *application) rateLimitExceededResponse(w http.ResponseWriter, r *http.Request) {
message := "rate limit exceeded"
app.errorResponse(w, r, http.StatusTooManyRequests, message)
}

View File

@@ -2,6 +2,7 @@ package main
import (
"fmt"
"golang.org/x/time/rate"
"net/http"
)
@@ -22,3 +23,19 @@ func (app *application) recoverPanic(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
})
}
func (app *application) rateLimit(next http.Handler) http.Handler {
// Initialize a new rate limiter which allows an overage of 2 requests per second, with a maximum of 4 requests in a single `burst`
limiter := rate.NewLimiter(2, 4)
// The function we are returning is a closure, which 'closes over' the limiter variable
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Call limiter.Allow() to see if the request is permitted, and if it's not, then we call the rateLimitExceededResponse() helper to return a 429 Too Many Requests response (we will create this helper in a minute).
if !limiter.Allow() {
app.rateLimitExceededResponse(w, r)
return
}
next.ServeHTTP(w, r)
})
}

View File

@@ -31,5 +31,6 @@ func (app *application) routes() http.Handler {
// Return the httprouter instance.
// Wrap the router with the panic recovery middleware
return app.recoverPanic(router)
// Wrap the router with the rateLimit() middleware
return app.recoverPanic(app.rateLimit(router))
}