go-chi / httprate

net/http rate limiter middleware
MIT License
270 stars 18 forks source link

Implement rate-limiting from HTTP handler (e.g. by request payload) #42

Closed VojtechVitek closed 2 months ago

VojtechVitek commented 2 months ago

Add support to rate-limit by custom key from HTTP handler (e.g. by request payload fields)

// Rate-limiter for login endpoint.
loginRateLimiter := httprate.NewRateLimiter(5, time.Minute)

r.Post("/login", func(w http.ResponseWriter, r *http.Request) {
    var payload struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    err := json.NewDecoder(r.Body).Decode(&payload)
    if err != nil || payload.Username == "" || payload.Password == "" {
        w.WriteHeader(400)
        return
    }

    // Rate-limit login at 5 req/min.
    if loginRateLimiter.OnLimit(w, r, payload.Username) {
        return
    }

    w.Write([]byte("login at 5 req/min\n"))
})
github-actions[bot] commented 2 months ago

Benchmark Results

goos: linux
goarch: amd64
pkg: github.com/go-chi/httprate
cpu: AMD EPYC 7763 64-Core Processor                
               │ master.txt  │            pr.txt             │
               │   sec/op    │   sec/op     vs base          │
LocalCounter-4   19.72m ± 1%   19.77m ± 1%  ~ (p=0.280 n=10)

               │  master.txt  │             pr.txt             │
               │     B/op     │     B/op      vs base          │
LocalCounter-4   2.831Mi ± 0%   2.834Mi ± 0%  ~ (p=0.218 n=10)

               │ master.txt  │            pr.txt             │
               │  allocs/op  │  allocs/op   vs base          │
LocalCounter-4   121.4k ± 0%   121.5k ± 0%  ~ (p=0.280 n=10)