ratelimit

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 15, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package ratelimit provides HTTP rate limiting middleware with support for per-principal and per-application rate limits.

The package supports multiple storage backends (in-memory, Redis) and integrates with Cedar policies for dynamic tier-based rate limiting.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRateLimitExceeded = errors.New("rate limit exceeded")
	ErrStorageFailure    = errors.New("rate limit storage failure")
)

Common errors returned by the rate limiter.

Functions

func NewRedisClient

func NewRedisClient(cfg *RedisConfig) redis.UniversalClient

NewRedisClient creates a Redis client from configuration.

Types

type CoreAPIResolver

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

CoreAPIResolver adapts coreapi.PolicyStore to the LimitResolver interface. It looks up rate limit policies based on the OAuth client ID from JWT claims.

func NewCoreAPIResolver

func NewCoreAPIResolver(store coreapi.PolicyStore, opts ...CoreAPIResolverOption) *CoreAPIResolver

NewCoreAPIResolver creates a LimitResolver that uses coreapi.PolicyStore.

func (*CoreAPIResolver) GetPolicyForRequest

func (r *CoreAPIResolver) GetPolicyForRequest(ctx context.Context, req *http.Request) *coreapi.RateLimitPolicy

GetPolicyForRequest returns the policy that would be applied to a request. Useful for debugging and displaying policy info in responses.

func (*CoreAPIResolver) InvalidateCache

func (r *CoreAPIResolver) InvalidateCache(clientID string)

InvalidateCache clears the policy cache.

func (*CoreAPIResolver) Resolve

func (r *CoreAPIResolver) Resolve(ctx context.Context, key string, req *http.Request) Limit

Resolve implements LimitResolver by looking up the policy for the OAuth client.

type CoreAPIResolverOption

type CoreAPIResolverOption func(*CoreAPIResolver)

CoreAPIResolverOption configures a CoreAPIResolver.

func WithResolverCache

func WithResolverCache(ttl time.Duration) CoreAPIResolverOption

WithResolverCache enables caching of policy lookups.

type KeyFunc

type KeyFunc func(r *http.Request) string

KeyFunc extracts the rate limit key from a request. Common implementations include extracting principal ID or client ID from JWT.

func ClientEndpointKey

func ClientEndpointKey() KeyFunc

ClientEndpointKey is a convenience function combining ClientKey with EndpointKey.

func ClientKey

func ClientKey() KeyFunc

ClientKey returns a KeyFunc that extracts the OAuth client ID (azp) from JWT claims. Falls back to IP address if no client ID is present.

func CompositeKey

func CompositeKey() KeyFunc

CompositeKey returns a KeyFunc that combines principal and client IDs. Format: "pid:{principal_id}:client:{client_id}" or fallback to IP.

func EndpointKey

func EndpointKey(inner KeyFunc) KeyFunc

EndpointKey wraps another KeyFunc to add endpoint-specific rate limiting. Format: "{inner_key}:path:{path}:method:{method}"

func IPKey

func IPKey() KeyFunc

IPKey returns a KeyFunc that uses the client's IP address.

func PrincipalEndpointKey

func PrincipalEndpointKey() KeyFunc

PrincipalEndpointKey is a convenience function combining PrincipalKey with EndpointKey.

func PrincipalKey

func PrincipalKey() KeyFunc

PrincipalKey returns a KeyFunc that extracts the principal ID from JWT claims. Falls back to IP address if no principal is authenticated.

type Limit

type Limit struct {
	// Rate is the number of requests allowed per Period.
	Rate int

	// Period is the time window for the rate limit (e.g., time.Minute).
	Period time.Duration

	// Burst is the maximum number of requests allowed in a single burst.
	// If zero, defaults to Rate.
	Burst int
}

Limit defines rate limit parameters.

func DefaultLimit

func DefaultLimit() Limit

DefaultLimit returns a sensible default rate limit (100 requests per minute).

func PerHour

func PerHour(n int) Limit

PerHour creates a rate limit of n requests per hour.

func PerMinute

func PerMinute(n int) Limit

PerMinute creates a rate limit of n requests per minute.

func PerSecond

func PerSecond(n int) Limit

PerSecond creates a rate limit of n requests per second.

type LimitResolver

type LimitResolver interface {
	// Resolve returns the rate limit for the given key and context.
	// The key is typically derived from the principal ID or client ID.
	Resolve(ctx context.Context, key string, r *http.Request) Limit
}

LimitResolver determines the rate limit for a given request. This allows dynamic rate limiting based on user tier, endpoint, etc.

type Limiter

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

Limiter is the main rate limiter type.

func New

func New(storage Storage, opts ...Option) *Limiter

New creates a new Limiter with the given storage and options.

func (*Limiter) Allow

func (l *Limiter) Allow(r *http.Request) (Result, error)

Allow checks if a request should be allowed.

func (*Limiter) Close

func (l *Limiter) Close() error

Close releases resources held by the limiter.

func (*Limiter) Middleware

func (l *Limiter) Middleware() func(http.Handler) http.Handler

Middleware returns an HTTP middleware that enforces rate limits.

type MemoryOption

type MemoryOption func(*MemoryStorage)

MemoryOption configures MemoryStorage.

func WithCleanupInterval

func WithCleanupInterval(d time.Duration) MemoryOption

WithCleanupInterval sets the interval for cleaning up expired windows.

type MemoryStorage

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

MemoryStorage is an in-memory rate limit storage using sliding window algorithm. Suitable for single-instance deployments and development/testing.

func NewMemoryStorage

func NewMemoryStorage(opts ...MemoryOption) *MemoryStorage

NewMemoryStorage creates a new in-memory rate limit storage.

func (*MemoryStorage) Allow

func (m *MemoryStorage) Allow(ctx context.Context, key string, limit Limit) (Result, error)

Allow implements Storage.Allow using a sliding window algorithm.

func (*MemoryStorage) Close

func (m *MemoryStorage) Close() error

Close implements Storage.Close.

func (*MemoryStorage) Reset

func (m *MemoryStorage) Reset(ctx context.Context, key string) error

Reset implements Storage.Reset.

type Option

type Option func(*Limiter)

Option configures a Limiter.

func WithKeyFunc

func WithKeyFunc(keyFunc KeyFunc) Option

WithKeyFunc sets the function to extract rate limit keys from requests.

func WithLimit

func WithLimit(limit Limit) Option

WithLimit sets a static rate limit.

func WithObservability

func WithObservability(obs *observability.Observability) Option

WithObservability sets the observability provider for metrics and tracing.

func WithResolver

func WithResolver(resolver LimitResolver) Option

WithResolver sets a custom limit resolver.

type RedisConfig

type RedisConfig struct {
	// Addr is the Redis server address (e.g., "localhost:6379").
	Addr string

	// Password is the Redis password (optional).
	Password string

	// DB is the Redis database number (default 0).
	DB int

	// PoolSize is the maximum number of connections (default 10).
	PoolSize int

	// Cluster enables Redis Cluster mode.
	Cluster bool

	// ClusterAddrs are the cluster node addresses (used when Cluster is true).
	ClusterAddrs []string
}

RedisConfig contains configuration for connecting to Redis.

type RedisOption

type RedisOption func(*RedisStorage)

RedisOption configures RedisStorage.

func WithKeyPrefix

func WithKeyPrefix(prefix string) RedisOption

WithKeyPrefix sets a prefix for all rate limit keys in Redis.

type RedisStorage

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

RedisStorage is a Redis-backed rate limit storage using sliding window algorithm. Suitable for distributed deployments where multiple instances share rate limit state.

func NewRedisStorage

func NewRedisStorage(client redis.UniversalClient, opts ...RedisOption) *RedisStorage

NewRedisStorage creates a new Redis-backed rate limit storage. The client can be *redis.Client, *redis.ClusterClient, or any UniversalClient.

func (*RedisStorage) Allow

func (r *RedisStorage) Allow(ctx context.Context, key string, limit Limit) (Result, error)

Allow implements Storage.Allow using a sliding window algorithm with Redis.

func (*RedisStorage) Close

func (r *RedisStorage) Close() error

Close implements Storage.Close. Note: This does NOT close the Redis client since it may be shared.

func (*RedisStorage) Reset

func (r *RedisStorage) Reset(ctx context.Context, key string) error

Reset implements Storage.Reset.

type Result

type Result struct {
	// Allowed is true if the request should be permitted.
	Allowed bool

	// Remaining is the number of requests remaining in the current window.
	Remaining int

	// ResetAt is when the rate limit window resets.
	ResetAt time.Time

	// RetryAfter is the duration to wait before retrying (only set if not allowed).
	RetryAfter time.Duration
}

Result contains the outcome of a rate limit check.

type StaticResolver

type StaticResolver struct {
	Limit Limit
}

StaticResolver always returns the same limit.

func (*StaticResolver) Resolve

func (s *StaticResolver) Resolve(ctx context.Context, key string, r *http.Request) Limit

Resolve implements LimitResolver.

type Storage

type Storage interface {
	// Allow checks if a request should be allowed and updates the counter.
	// Returns the result of the check and any error.
	Allow(ctx context.Context, key string, limit Limit) (Result, error)

	// Reset clears the rate limit state for a key.
	Reset(ctx context.Context, key string) error

	// Close releases any resources held by the storage.
	Close() error
}

Storage defines the interface for rate limit state storage.

type TieredResolver

type TieredResolver struct {
	Tiers    map[string]Limit
	Default  Limit
	TierFunc func(ctx context.Context, key string, r *http.Request) string
	// contains filtered or unexported fields
}

TieredResolver returns different limits based on tier.

func (*TieredResolver) Resolve

func (t *TieredResolver) Resolve(ctx context.Context, key string, r *http.Request) Limit

Resolve implements LimitResolver.

Jump to

Keyboard shortcuts

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