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
- Variables
- func ContextWithAuthToken(ctx context.Context, token string) context.Context
- func ContextWithClientIP(ctx context.Context, ip string) context.Context
- func ExtractAuthToken(ctx context.Context) string
- func ExtractClientIp(ctx context.Context) string
- type ClientService
- type ClientServiceFunc
- type ExtractIPFunc
- type ExtractTokenFunc
- type LimitInfo
- type Option
- type ParsedRule
- type RateLimitConfig
- type RateLimitRule
- type RateLimitSettings
- type RuleLimiter
Constants ¶
const (
// DefaultCacheSize is the default size for the IP cache.
DefaultCacheSize = 1000
)
Variables ¶
var ErrLimitExceeded = limiters.ErrLimitExceeded
ErrLimitExceeded is an alias for the shared ErrLimitExceeded error.
var ErrNoIPFoundOrInvalid = errors.New("no client IP found or invalid IP address")
ErrNoIPFoundOrInvalid is returned when client IP cannot be determined.
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.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 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 ¶
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 ¶
WithIPCacheSize sets the iPCacheSize 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:
- Exact IP addresses (e.g., "192.168.1.100")
- 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)