The deprecated LimitByIP and LimitByRealIP functions are insecure or incorrect for production environments behind a reverse proxy (like Nginx, Cloudflare, or a Load Balancer).
LimitByIP (and KeyByIP) uses r.RemoteAddr, which will point to your proxy's IP, causing all users to share a single rate-limit bucket.LimitByRealIP (and KeyByRealIP) trusts client-supplied headers like X-Forwarded-For, which can be easily spoofed by attackers to evade limits or perform Denial of Service attacks on other users.
Recommended Secure Pattern:
Use one of chi's middleware.ClientIPFrom* middlewares (available in chi v5.3.0+) to resolve the true client IP, then use httprate.LimitBy with httprate.CanonicalizeIP to bucket requests. CanonicalizeIP buckets IPv6 addresses by their /64 prefix.
// 1. Install chi middleware to resolve the IP from a trusted source (e.g., XFF)
r.Use(middleware.ClientIPFromXFF("10.0.0.0/8"))
// 2. Use LimitBy with a key function that reads the resolved IP from context
r.Use(httprate.LimitBy(100, time.Minute, func(r *http.Request) (string, error) {
return httprate.CanonicalizeIP(middleware.GetClientIP(r.Context())), nil
}))
// Directly exposed to clients (equivalent to old LimitByIP behavior):
r.Use(middleware.ClientIPFromRemoteAddr)
r.Use(httprate.LimitBy(requestLimit, windowLength, func(r *http.Request) (string, error) {
return httprate.CanonicalizeIP(middleware.GetClientIP(r.Context())), nil
}))