ratelimit

package
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: Apache-2.0 Imports: 9 Imported by: 6

Documentation

Overview

Package ratelimit provides token-bucket rate limiting keyed by a string (an IP address, account or API key): the Taker interface, an in-memory Limiter, and HTTP middleware.

The in-memory limiter is per process: behind several instances each one enforces its own limit. gorbital.dev/modules/ratelimitpg implements Taker with limits shared across instances (ADR-0052).

Stability: stable (ADR-0015, ADR-0054).

Index

Constants

View Source
const (
	DefaultIdleTTL = 10 * time.Minute
	DefaultMaxKeys = 100_000
)

Defaults for New.

Variables

View Source
var ErrEmptyKey = errors.New("ratelimit: empty key")

ErrEmptyKey reports a request without a key.

Functions

func ByRemoteIP

func ByRemoteIP(r *http.Request) string

ByRemoteIP keys requests by the connection's remote IP, grouped as ClientKey does. Behind a proxy, run trusted-proxy middleware first so RemoteAddr holds the client address.

func ClientKey

func ClientKey(ip string) string

ClientKey returns the rate-limit key of a client IP address: an IPv4 address as it is, and an IPv6 address as its /64 network, since one host or customer usually holds a whole /64 and could otherwise use a new address, and a new budget, for every request. IPv4-mapped IPv6 addresses count as IPv4, and zones are ignored. A value that isn't an IP address is returned unchanged.

func Middleware

func Middleware(l Taker, key KeyFunc, onLimit http.Handler) func(http.Handler) http.Handler

Middleware limits requests with l. Limited requests receive onLimit, or a 429 application/problem+json response with a Retry-After header when onLimit is nil. When l can't decide, the request proceeds.

Types

type Decision

type Decision struct {
	Allowed bool
	// RetryAfter is how long until a request may proceed, when not allowed.
	RetryAfter time.Duration
}

Decision is the outcome of one request against a limit.

type KeyFunc

type KeyFunc func(r *http.Request) string

KeyFunc extracts the rate-limit key from a request. An empty key skips limiting for that request.

type Limit

type Limit struct {
	PerSecond float64
	Burst     int
}

Limit is a token bucket: PerSecond requests on average, with bursts of up to Burst.

func Per

func Per(n int, window time.Duration) Limit

Per returns the limit of n requests per window, all of which may arrive at once.

func (Limit) Valid

func (l Limit) Valid() bool

Valid reports whether l allows any request.

type Limiter

type Limiter struct {
	// contains filtered or unexported fields
}

A Limiter tracks one token bucket per key. It is safe for concurrent use.

func New

func New(perSecond float64, burst int, opts ...Option) *Limiter

New returns a limiter allowing perSecond requests per key on average, with bursts of up to burst requests.

func (*Limiter) Allow

func (l *Limiter) Allow(key string) (ok bool, retryAfter time.Duration)

Allow reports whether a request for key may proceed. When it may not, retryAfter is how long until one token is available.

func (*Limiter) Take

func (l *Limiter) Take(_ context.Context, key string) (Decision, error)

Take implements Taker with Limiter.Allow; it never fails for a non-empty key.

type Option

type Option interface {
	// contains filtered or unexported methods
}

An Option configures a Limiter.

func WithClock

func WithClock(now func() time.Time) Option

WithClock sets the time source, for tests.

func WithIdleTTL

func WithIdleTTL(d time.Duration) Option

WithIdleTTL sets how long an unused key is remembered. Default: DefaultIdleTTL.

func WithMaxKeys

func WithMaxKeys(n int) Option

WithMaxKeys bounds memory use. When the limit is reached and no idle keys can be evicted, new keys are allowed without tracking (fail open), so a flood of distinct keys can't lock out all clients. Default: DefaultMaxKeys.

type Taker

type Taker interface {
	Take(ctx context.Context, key string) (Decision, error)
}

A Taker decides whether a request for key may proceed. An error means the limiter couldn't decide, and callers allow the request: implementations that can fail handle their own fallback.

Jump to

Keyboard shortcuts

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