ratelimit

package
v2.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package ratelimit provides bounded, per-client HTTP rate limiting.

New creates a middleware gate. Reusing the returned middleware shares one quota namespace; calling New again creates an independent namespace. The default client identity is the normalized transport peer in Request.RemoteAddr and does not trust forwarding headers.

Client storage is finite: zero IdleTTL and MaxClients values select the documented defaults in Config. IdleTTL is a minimum retention period; a bucket is always retained long enough to refill its full burst so pruning cannot reset a slow quota early. Idle buckets are pruned during requests; the gate starts no cleanup goroutine. When the pool is full, existing clients keep their buckets and a new client receives 429 Too Many Requests. Quota rejections also return 429 with Retry-After and RateLimit-Reset derived from the token schedule. Capacity rejections use the effective retention as a conservative backoff.

Applications behind known reverse proxies can opt in to X-Forwarded-For parsing with TrustedProxyClientKey. Other forwarding headers are ignored.

A gate can be placed in front of any standard net/http handler:

gate, err := ratelimit.New(ratelimit.Config{
	RequestsPerSecond: 20,
	Burst:             40,
})
if err != nil {
	log.Fatal(err)
}
handler := gate(next)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(config Config) (func(http.Handler) http.Handler, error)

New validates config and returns standard net/http middleware. Each call to New owns a separate quota namespace. Reusing the returned function shares its quotas, including when it is mounted on multiple paths.

Types

type Config

type Config struct {
	// RequestsPerSecond is the sustained token refill rate. It must be finite
	// and greater than zero.
	RequestsPerSecond float64

	// Burst is the maximum number of tokens available at once. It must be
	// greater than zero.
	Burst int

	// ClientKey selects the quota identity. Nil uses the normalized transport
	// peer from Request.RemoteAddr and never trusts forwarding headers.
	ClientKey KeyFunc

	// IdleTTL is the minimum time an unused client bucket is retained before
	// opportunistic pruning. To prevent quota resets, the effective retention
	// is never shorter than the time needed to refill Burst tokens. Zero
	// selects the finite default of 10 minutes.
	IdleTTL time.Duration

	// MaxClients bounds the number of client buckets. Zero selects the finite
	// default of 10,000. At capacity, new clients are rejected rather than
	// replacing an active bucket.
	MaxClients int
}

Config configures one independent rate-limit quota namespace.

type KeyFunc

type KeyFunc func(*http.Request) (string, error)

KeyFunc returns the quota key for a request. Keys must be non-empty and at most 512 bytes. Returning an error rejects the request without invoking the next handler.

func TrustedProxyClientKey

func TrustedProxyClientKey(proxyRanges []netip.Prefix) (KeyFunc, error)

TrustedProxyClientKey returns a KeyFunc that accepts X-Forwarded-For only from an immediate transport peer in proxyRanges. It parses every hop and walks right-to-left, through trusted proxies, to the first untrusted client. Malformed headers, headers received from an untrusted peer, and chains with no untrusted client fail closed. With no X-Forwarded-For header, the transport peer remains the client identity.

The prefix slice is validated, normalized, and copied. At least one valid, unzoned prefix is required.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL