oakratelimiter

package
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2023 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var SkipTagger = errors.New("discriminator did not match")

SkipTagger is a sentinel error used to indicate that a certain http.Request must be disregarded for rate limiting purposes.

revive:disable-next-line:error-naming

Functions

func GetRequestFactory

func GetRequestFactory(ctx context.Context) *http.Request

GetRequestFactory is the simplest request factory with no payload.

func MiddlewareLoadTest

func MiddlewareLoadTest(
	ctx context.Context,
	m oakhttp.Middleware,
	r Rate,
	rf RequestFactory,
	expectedRejectionRate float64,
) func(t *testing.T)

MiddlewareLoadTest runs a stream of requests while context.Context is active against a given rate limiting oakhttp.Middleware. Ensures that the failure rate roughly matches the expected failure rate. Use this helper to build and test your own rate limiting middlewares.

func New

func New(withOptions ...Option) (oakhttp.Middleware, error)

New creates an oakhttp.Middleware from either Basic, SingleTagging, or MultiTagging rate limiters. The selection is based on the [Option]s provided. If the option set contains no request [Tagger]s, Basic middleware is returned. If one Tagger, then SingleTagging. If more than one Tagger, then MultiTagging. This function is able to instrument a performant RateLimiter for most practical cases.

If you would like more exact or partially obfuscated configuration, use NewBasic, NewSingleTagging, NewMultiTagging with NewMiddleware constructors.

func NewMiddleware

func NewMiddleware(l RateLimiter, displayRate Rate) oakhttp.Middleware

NewMiddleware protects an oakhttp.Handler using a RateLimiter. The display Rate can be used to obfuscate the true RateLimiter throughput. HTTP headers are set to promise availability of no more than one call. This is done to conceal the performance capacity of the system, while giving some useful information to API callers regarding service availability. "X-RateLimit-*" headers are experimental, inconsistent in implementation, and meant to be approximate. If display Rate is 0, the headers are ommitted.

func NewTooManyRequestsError

func NewTooManyRequestsError(causes ...error) error

NewTooManyRequestsError returns a TooManyRequestsError if at least one of the causes is not <nil>. Otherwise, returns <nil>.

Types

type Basic

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

Basic rate limiter enforces the limit using one leaky token bucket.

func NewBasic

func NewBasic(withOptions ...LimitOption) (*Basic, error)

NewBasic initializes a Basic rate limiter.

func (*Basic) Expires

func (b *Basic) Expires(at time.Time) bool

Expires returns true if the bucket is expired at given time.Time.

func (*Basic) Middleware

func (b *Basic) Middleware() oakhttp.Middleware

Middleware creates an oakhttp.Middleware from the Basic rate limiter.

func (*Basic) ObfuscatedMiddleware

func (b *Basic) ObfuscatedMiddleware(displayRate Rate) oakhttp.Middleware

ObfuscatedMiddleware creates an oakhttp.Middleware from the Basic rate limiter with a display Rate different from the actual.

func (*Basic) Rate

func (b *Basic) Rate() Rate

Rate returns the rate limiter Rate.

func (*Basic) Take

func (b *Basic) Take(r *http.Request) error

Take consumes one token per request. Returns a TooManyRequestsError if the leaky bucket is drained.

type ContextTagger

type ContextTagger func(context.Context) (string, error)

ContextTagger is used together with NewRequestTaggerFromContextTagger to tag requests based on context values. This can help with rate-limiting requests by a role.

type LimitOption

type LimitOption func(*limitOptions) error

LimitOption configures a rate limitter. Basic relies on one set of [LimitOption]s. SingleTagging and MultiTagging use a set for superivising rate limit and additional sets for each Tagger.

func WithDefaultInitialAllocationSize

func WithDefaultInitialAllocationSize() LimitOption

WithDefaultInitialAllocationSize sets initial map allocation to 1024.

func WithDefaultName

func WithDefaultName() LimitOption

WithDefaultName sets rate limiter name to "default."

func WithInitialAllocationSize

func WithInitialAllocationSize(buckets int) LimitOption

WithInitialAllocationSize sets the number of pre-allocated items for a tagged bucket map. Higher number can improve initial performance at the cost of using more memory.

func WithName

func WithName(name string) LimitOption

WithName associates a name with a rate limiter. It is displayed only in the logs.

func WithRate

func WithRate(limit float64, interval time.Duration) LimitOption

type MultiTagging

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

MultiTagging rate limiter takes from the superivising bucket and a list of tagged bucket maps. It is the most flexible of the [RateLimiter]s and the least performant.

func NewMultiTagging

func NewMultiTagging(withOptions ...Option) (*MultiTagging, error)

NewMultiTagging initializes a MultiTagging rate limiter.

func (*MultiTagging) Expires

func (b *MultiTagging) Expires(at time.Time) bool

Expires returns true if the bucket is expired at given time.Time.

func (*MultiTagging) Middleware

func (d *MultiTagging) Middleware() oakhttp.Middleware

Middleware calls NewMiddleware with MultiTagging as parameter.

func (*MultiTagging) ObfuscatedMiddleware

func (d *MultiTagging) ObfuscatedMiddleware(displayRate Rate) oakhttp.Middleware

Middleware calls NewMiddleware with MultiTagging as parameter and a different display rate.

func (*MultiTagging) Rate

func (d *MultiTagging) Rate() (r Rate)

Rate returns discriminating Rate or global Rate, whichever is slower.

func (*MultiTagging) Take

func (d *MultiTagging) Take(r *http.Request) (err error)

Take first takes from supervising bucket, and then from the tagged bucket maps.

type Option

type Option func(*options) error

Option initializes a RateLimiter.

func WithCleanUpPeriod

func WithCleanUpPeriod(of time.Duration) Option

WithCleanUpPeriod sets the frequency of map clean up. Lower value frees up more memory at the cost of CPU cycles.

func WithCookieTagger

func WithCookieTagger(name, noCookieValue string, withOptions ...LimitOption) Option

WithCookieTagger configures rate limiter to track requests based on a certain cookie. If [noCookieValue] is an empty string, this Tagger issues a SkipTagger sentinel value.

func WithDefaultCleanUpPeriod

func WithDefaultCleanUpPeriod() Option

WithDefaultCleanUpPeriod sets clean up period to 15 minutes.

func WithIPAddressTagger

func WithIPAddressTagger(withOptions ...LimitOption) Option

WithIPAddressTagger configures rate limiter to track requests based on client IP addresses.

func WithRequestTagger

func WithRequestTagger(t Tagger, withOptions ...LimitOption) Option

WithRequestTagger associates a request Tagger with a RateLimiter. [Tagger]s allow you to differentiate and group requests based on their properties.

func WithSupervisingLimit

func WithSupervisingLimit(withOptions ...LimitOption) Option

WithSupervisingLimit sets the top rate limit for either SingleTagging or MultiTagging rate limiters to prevent [Tagger]s from consuming too much memory. Should be higher than the limit of any request tagger.

type Rate

type Rate float64

Rate is the number of tokens leaked or replenished per nanosecond.

func NewRate

func NewRate(limit float64, interval time.Duration) Rate

NewRate creates a Rate based on expected limit and a given time interval.

func (Rate) ReplenishedTokens

func (r Rate) ReplenishedTokens(from, to time.Time) float64

ReplenishedTokens returns fractional token amount based on time passed.

type RateLimiter

type RateLimiter interface {
	Take(*http.Request) error
}

RateLimiter contrains the number of requests to a certain Rate. When it is exceeded, it should return TooManyRequestsError.

type RequestFactory

type RequestFactory func(context.Context) *http.Request

RequestFactory generates new requests for load testing rate limiting middleware. Use together with MiddlewareLoadTest.

type SingleTagging

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

SingleTagging is a faster version of MultiTagging for situations where only one Tagger is sufficient.

func NewSingleTagging

func NewSingleTagging(withOptions ...Option) (*SingleTagging, error)

NewSingleTagging initializes a SingleTagging rate limiter.

func (*SingleTagging) Expires

func (b *SingleTagging) Expires(at time.Time) bool

Expires returns true if the bucket is expired at given time.Time.

func (*SingleTagging) Middleware

func (d *SingleTagging) Middleware() oakhttp.Middleware

Middleware calls NewMiddleware with SingleTagging as parameter.

func (*SingleTagging) ObfuscatedMiddleware

func (d *SingleTagging) ObfuscatedMiddleware(displayRate Rate) oakhttp.Middleware

Middleware calls NewMiddleware with SingleTagging as parameter and a different display rate.

func (*SingleTagging) Rate

func (d *SingleTagging) Rate() Rate

Rate returns discriminating Rate or global Rate, whichever is slower.

func (*SingleTagging) Take

func (d *SingleTagging) Take(r *http.Request) (err error)

Take first takes from supervising bucket, and then from the tagged bucket map.

type Tagger

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

Tagger associates tags to [http.Request]s in order to group related requests for a discriminating rate limiter. Requests with the same association tag will be tracked together by the RateLimiter. Return SkipTagger sentinel value to disregard the http.Request.

func NewCookieTagger

func NewCookieTagger(name, noCookieValue string) Tagger

NewCookieTagger tags requests by certain cookie value. If [noCookieValue] is an empty string, this tagger issues SkipTagger.

func NewHeaderTagger

func NewHeaderTagger(name, noHeaderValue string) Tagger

NewHeaderTagger tags requests by certain header value. If [noHeaderValue] is an empty string, this tagger issues SkipTagger.

func NewIPAddressTagger

func NewIPAddressTagger() Tagger

NewIPAddressTagger tags requests by client IP address.

func NewIPAddressWithPortTagger

func NewIPAddressWithPortTagger() Tagger

NewIPAddressTagger tags requests by client IP address and port. It is slightly faster than NewIPAddressTagger.

func NewRequestTaggerFromContextTagger

func NewRequestTaggerFromContextTagger(t ContextTagger) Tagger

NewRequestTaggerFromContextTagger adapts a ContextTagger to a Tagger.

type TooManyRequestsError

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

TooManyRequestsError indicates overflowing request Rate.

func (*TooManyRequestsError) Error

func (e *TooManyRequestsError) Error() string

Error returns a generic text, regardless of what caused the TooManyRequestsError.

func (*TooManyRequestsError) HTTPStatusCode

func (e *TooManyRequestsError) HTTPStatusCode() int

HTTPStatusCode presents a standard HTTP status code.

func (*TooManyRequestsError) LogValue

func (e *TooManyRequestsError) LogValue() slog.Value

LogValue captures causes into structured log entries.

func (*TooManyRequestsError) Unwrap

func (e *TooManyRequestsError) Unwrap() []error

Unwrap returns the list of reasons for TooManyRequestsError.

Jump to

Keyboard shortcuts

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