This is a generic middleware to rate-limit HTTP requests. It's forked from tollbooth, removing unnecessary third-party dependencies.
package main
import (
"github.com/Q42Philips/tollbooth"
"net/http"
"time"
)
func HelloHandler(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("Hello, World!"))
}
func main() {
// Create a request limiter per handler.
http.Handle("/", tollbooth.LimitFuncHandler(tollbooth.NewLimiter(1, time.Second), HelloHandler))
http.ListenAndServe(":12345", nil)
}
-
Rate-limit by request's remote IP, path, methods, custom headers, & basic auth usernames.
limiter := tollbooth.NewLimiter(1, time.Second) // or create a limiter with expirable token buckets // This setting means: // create a 1 request/second limiter and // every token bucket in it will expire 1 hour after it was initially set. limiter = tollbooth.NewLimiterExpiringBuckets(1, time.Second, time.Hour, 0) // Configure list of places to look for IP address. // By default it's: "RemoteAddr", "X-Forwarded-For", "X-Real-IP" // If your application is behind a proxy, set "X-Forwarded-For" first. limiter.IPLookups = []string{"RemoteAddr", "X-Forwarded-For", "X-Real-IP"} // Configure number of steps to take in X-Forwarded-For list. // By default it's 0. This checks the first IP from the list. // Set to -1 to get the last or -2 to get the second-to-last. limiter.XForwardedForIndex = 0 // Add a function to be called when a request is rejected. limiter.RejectFunc = func() { fmt.Println("A request was rejected") } // Limit only GET and POST requests. limiter.Methods = []string{"GET", "POST"} // Limit request headers containing certain values. // Typically, you prefetched these values from the database. limiter.Headers = make(map[string][]string) limiter.Headers["X-Access-Token"] = []string{"abc123", "xyz098"} // Limit based on basic auth usernames. // Typically, you prefetched these values from the database. limiter.BasicAuthUsers = []string{"bob", "joe", "didip"}
-
Each request handler can be rate-limited individually.
-
Compose your own middleware by using
LimitByKeys()
. -
Tollbooth does not require external storage since it uses an algorithm called Token Bucket (Go library: golang.org/x/time/rate).