Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rate limit with golang.org/x/time/rate api request

Tags:

go

limit

rate

I already created a function for limiting to 50 requests for API logins in one day.

var limit = 50

package middleware

import (
    "log"
    "net"
    "net/http"
    "sync"
    "time"

    "golang.org/x/time/rate"
)

// Create a custom request struct which holds the rate limiter for each
// visitor and the last time that the request was seen.
type request struct {
    limiter  *rate.Limiter
    lastSeen time.Time
}

// Change the the map to hold values of the type request.
// defaultTime using 3 minutes
var requests = make(map[string]*request)
var mu sync.Mutex

func getRequest(ip string, limit int) *rate.Limiter {
    mu.Lock()
    defer mu.Unlock()

    v, exists := requests[ip]
    if !exists {
        limiter := rate.NewLimiter(1, limit)
        requests[ip] = &request{limiter, time.Now()}
        return limiter
    }
    // Update the last seen time for the visitor.
    v.lastSeen = time.Now()
    return v.limiter
}

func throttle(next http.Handler, limit int) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip, _, err := net.SplitHostPort(r.RemoteAddr)
        if err != nil {
            log.Println(err.Error())
            http.Error(w, "Internal Server Error", http.StatusInternalServerError)
            return
        }
        limiter := getRequest(ip, limit)
        fmt.Println(limiter.Allow())
        if limiter.Allow() == false {
            http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }
        next.ServeHTTP(w, r)
    })
}

Is it correct?

Because when I try it, it still passes. The function limit is not working.

I doubt with NewLimiter()

 limiter := rate.NewLimiter(1, limit)

Does it mean one user only can request login 50 requests per day? (I already read the docs, but I do not understand.)

like image 421
agny reza Avatar asked Sep 16 '25 06:09

agny reza


1 Answers

From the rate docs:

func NewLimiter(r Limit, b int) *Limiter

NewLimiter returns a new Limiter that allows events up to rate r and permits bursts of at most b tokens.


So the first parameter is the rate-limit, not the second. Burst is the number of requests you want to allow that occur faster than the rate-limit - typically one uses a value of 1 to disallow bursting, anything higher will let this number of requests in before the regular rate-limit kicks in. Anyway...

To create the rate.Limit for your needs, you can use the helper function rate.Every():

rt := rate.Every(24*time.Hour / 50)

limiter := rate.NewLimiter(rt, 1)
like image 173
colm.anseo Avatar answered Sep 19 '25 15:09

colm.anseo