tokenbucket

package
v0.0.0-...-b788499 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 17 Imported by: 0

README

tokenbucket

import "github.com/altessa-s/go-atlas/data/limiters/tokenbucket"

Package tokenbucket implements rule-based rate limiting using a sliding window algorithm. Supports IP/CIDR-based rules, client-specific limits, and authentication token extraction with configurable storage backends and sophisticated rule matching that prioritizes more specific rules.

Options

Option Default Description
WithIPCacheSize 1000 LRU cache capacity for IP lookup
WithExtractToken noop Function to extract auth token
WithExtractClientIPAddress noop Function to extract client IP
WithClientService nil Client-specific rate limit service
WithLogger discard Structured logger

Subpackages

Package Description
factory Configuration-based creation
storages/memory In-memory storage backend
storages/redis Distributed Redis storage
storages/nats NATS KV storage backend

Documentation

Overview

Package tokenbucket implements rule-based rate limiting using a sliding window algorithm. It provides IP/CIDR-based rate limiting, client-specific limits, and authentication token support with configurable storage backends and sophisticated rule matching that prioritizes specific rules.

The RuleLimiter is thread-safe and can be used concurrently from multiple goroutines. It automatically handles rule matching, IP caching with LRU algorithm, and storage backend operations.

Features

  • Rule-based limiting: support for default, CIDR, and specific client rules.
  • Pluggable storage: memory (single-instance) or Redis/NATS (distributed).
  • Advanced matching: prioritizes more specific rules over broader ones.
  • Performance: uses LRU cache for IP classification to minimize storage hits.

Usage

storage := memory.New()
config := &RateLimitConfig{
    Default: RateLimitSettings{Limit: 100, Period: time.Minute},
    Rules: []RateLimitRule{
        {CIDR: "192.168.1.0/24", Settings: RateLimitSettings{Limit: 1000}},
    },
}
limiter := New(config, storage)
defer storage.Close()

if allowed, _ := limiter.Allow(ctx, "192.168.1.5", ""); !allowed {
    // rate limited
}

Index

Constants

View Source
const (
	// DefaultCacheSize is the default size for the IP cache.
	DefaultCacheSize = 1000
)

Variables

View Source
var ErrLimitExceeded = limiters.ErrLimitExceeded

ErrLimitExceeded is an alias for the shared ErrLimitExceeded error.

View Source
var ErrNoIPFoundOrInvalid = errors.New("no client IP found or invalid IP address")

ErrNoIPFoundOrInvalid is returned when client IP cannot be determined.

View Source
var RateLimitSkip = &RateLimitSettings{
	Limit:  math.MinInt64,
	Period: math.MinInt64,
}

RateLimitSkip is a predefined RateLimitSettings instance that effectively disables rate limiting. It can be used in scenarios where rate limiting should be bypassed entirely. Note: Limit and Period are set to MinInt64 to signify skipping rate limiting.

View Source
var RateLimitUnlimited = &RateLimitSettings{
	Limit:  math.MaxInt64,
	Period: math.MaxInt64,
}

RateLimitUnlimited is a predefined RateLimitSettings instance that represents no rate limiting. It can be used to indicate that a client or IP address has unlimited access. Note: Limit is set to MaxInt64 to signify no limit, and Period is set to MaxInt64.

Functions

func ContextWithAuthToken

func ContextWithAuthToken(ctx context.Context, token string) context.Context

ContextWithAuthToken returns a new context that carries the authentication token. The transport layer should call this before invoking Limit() so that ExtractAuthToken can retrieve the token without transport-specific dependencies.

func ContextWithClientIP

func ContextWithClientIP(ctx context.Context, ip string) context.Context

ContextWithClientIP returns a new context that carries the client IP address. The transport layer should call this before invoking Limit() so that ExtractClientIp can retrieve the IP without transport-specific dependencies.

func ExtractAuthToken

func ExtractAuthToken(ctx context.Context) string

ExtractAuthToken extracts the authentication token from the context bridge. The transport layer must call ContextWithAuthToken before invoking Limit() so that this function can retrieve the token. Returns empty string if no token is found in the context.

func ExtractClientIp

func ExtractClientIp(ctx context.Context) string

ExtractClientIp extracts the client IP address from the context bridge. The transport layer must call ContextWithClientIP before invoking Limit() so that this function can retrieve the IP. Returns empty string if no IP is found in the context.

Types

type ClientService

type ClientService interface {
	// Settings returns rate limits for a token. Return RateLimitSkip for IP fallback.
	Settings(ctx context.Context, token string) (*RateLimitSettings, error)
}

ClientService retrieves rate limit settings for authenticated clients. Implementations must be safe for concurrent use.

type ClientServiceFunc

type ClientServiceFunc func(ctx context.Context, token string) (*RateLimitSettings, error)

ClientServiceFunc is a function adapter for ClientService.

func (ClientServiceFunc) Settings

func (l ClientServiceFunc) Settings(ctx context.Context, token string) (*RateLimitSettings, error)

Settings calls the underlying function.

type ExtractIPFunc

type ExtractIPFunc func(ctx context.Context) string

ExtractIPFunc defines a function that extracts client IP addresses from context. It should return the most accurate client IP available, considering proxy headers and load balancer forwarding.

type ExtractTokenFunc

type ExtractTokenFunc func(ctx context.Context) string

ExtractTokenFunc defines a function that extracts authentication tokens from context. It receives the request context, returning the token string or empty string if no token is found.

type LimitInfo

type LimitInfo = limiters.LimitInfo

LimitInfo is an alias for the shared LimitInfo type.

type Option

type Option func(o *options)

Option is a functional option for configuring options.

func WithClientService

func WithClientService(v ClientService) Option

WithClientService sets the clientService option.

func WithCollector

func WithCollector(v metrics.Collector) Option

WithCollector sets the collector option.

func WithExtractClientIPAddress

func WithExtractClientIPAddress(v ExtractIPFunc) Option

WithExtractClientIPAddress sets the extractClientIPAddress option.

func WithExtractToken

func WithExtractToken(v ExtractTokenFunc) Option

WithExtractToken sets the extractToken option.

func WithIPCacheSize

func WithIPCacheSize(v int) Option

WithIPCacheSize sets the iPCacheSize option.

func WithLogger

func WithLogger(v *slog.Logger) Option

WithLogger sets the logger option.

type ParsedRule

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

ParsedRule holds a pre-parsed IP or CIDR for efficient matching.

type RateLimitConfig

type RateLimitConfig struct {
	// Default rate limit applied if no specific rule matches
	Default RateLimitSettings
	// Rules is a list of specific limits for IPs or subnets.
	// Rules are evaluated in order of specificity (IP before CIDR, smaller CIDR before larger).
	Rules []*RateLimitRule
}

RateLimitConfig defines the overall rate limiting configuration. It allows setting default limits and specific rules for IPs/subnets.

func (*RateLimitConfig) Validate

func (c *RateLimitConfig) Validate() error

Validate checks that the rate limit configuration is valid.

type RateLimitRule

type RateLimitRule struct {
	// Target is the IP address or CIDR subnet to apply this rule to.
	// Must be a valid IPv4 or IPv6 address or CIDR notation.
	// Examples: "192.168.1.1", "10.0.0.0/8", "2001:db8::/32"
	Target string
	// RateLimitSettings contains the rate limit parameters for this target.
	// Must not be nil and must pass validation.
	*RateLimitSettings
}

RateLimitRule defines the rate limit settings for a specific IP or subnet. Rules allow setting custom rate limits for specific network addresses, enabling different rate limits for different classes of clients.

Rules are processed in order of specificity during matching:

  1. Exact IP addresses (e.g., "192.168.1.100")
  2. CIDR subnets, most specific first (e.g., "/24" before "/16")

Common use cases:

  • Higher limits for internal networks
  • Lower limits for external/public networks
  • Special limits for known problematic IP ranges
  • Administrative access with unlimited rates

func (*RateLimitRule) Validate

func (r *RateLimitRule) Validate() error

Validate checks that the rate limit rule is valid and can be used for matching. It verifies that the target is a valid IP address or CIDR notation and that the embedded rate limit settings are valid.

Returns an error describing the validation failure, nil if valid.

type RateLimitSettings

type RateLimitSettings struct {
	// Limit is the maximum number of requests allowed within the time period.
	// Must be greater than 0. Higher values allow more requests.
	Limit int64
	// Period is the time window for which the limit applies.
	// Must be greater than 0. Longer periods allow burst behavior.
	Period time.Duration
}

RateLimitSettings defines the basic parameters for a rate limit. It specifies how many requests are allowed within a given time period using a sliding window algorithm. The combination of Limit and Period determines the maximum sustainable request rate.

Examples:

  • Limit: 100, Period: 1 minute = 100 requests per minute
  • Limit: 10, Period: 1 second = 10 requests per second
  • Limit: 1000, Period: 1 hour = 1000 requests per hour

func (*RateLimitSettings) IsSkip

func (s *RateLimitSettings) IsSkip() bool

IsSkip returns true if the rate limit settings indicate that rate limiting should be skipped.

func (*RateLimitSettings) IsUnlimited

func (s *RateLimitSettings) IsUnlimited() bool

IsUnlimited returns true if the rate limit settings indicate no limit.

func (*RateLimitSettings) LimitInfo

func (s *RateLimitSettings) LimitInfo() *LimitInfo

LimitInfo returns a LimitInfo snapshot derived from these settings. For unlimited settings, all fields are set to math.MaxInt64.

func (*RateLimitSettings) Validate

func (s *RateLimitSettings) Validate() error

Validate checks that the rate limit settings are valid and can be used for rate limiting operations. Both Limit and Period must be positive values.

Returns an error if the settings are invalid, nil otherwise.

type RuleLimiter

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

RuleLimiter provides rule-based rate limiting with IP/CIDR and token support. It is safe for concurrent use and uses LRU caching for IP lookups.

func New

func New(config *RateLimitConfig, storage storages.Storage, opts ...Option) (*RuleLimiter, error)

New creates a new RuleLimiter with the given config and storage. Returns an error if config is invalid or the IP cache cannot be created.

Example:

limiter, err := tokenbucket.New(config, storage)

func (*RuleLimiter) Limit

func (l *RuleLimiter) Limit(ctx context.Context) (*LimitInfo, error)

Limit applies rate limiting based on token or client IP. Returns ErrLimitExceeded if the limit is exceeded.

Example:

info, err := limiter.Limit(ctx)

Directories

Path Synopsis
Package factory provides a fluent builder for creating rate limiters from configuration.
Package factory provides a fluent builder for creating rate limiters from configuration.

Jump to

Keyboard shortcuts

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