throttled

package
Version: v2.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Feb 13, 2016 License: BSD-3-Clause, AGPL-3.0, Apache-2.0 Imports: 10 Imported by: 0

README

Throttled build status GoDoc

Package throttled implements different throttling strategies for controlling access to HTTP handlers.

As of July 27, 2015, the package is now located under its own GitHub organization and uses gopkg.in for versioning, please adjust your imports to gopkg.in/throttled/throttled.v1.

Installation

go get gopkg.in/throttled/throttled.v1/...

Interval

The Interval function creates a throttler that allows requests to go through at a controlled, constant interval. The interval may be applied to all requests (vary argument == nil) or independently based on vary-by criteria.

For example:

th := throttled.Interval(throttled.PerSec(10), 100, &throttled.VaryBy{Path: true}, 50)
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will allow a request each 100ms (10 requests per second), with a buffer of 100 exceeding requests before dropping requests with a status code 429 (by default, configurable using th.DeniedHandler or the package-global DefaultDeniedHandler variable). Different paths will be throttled independently, so that /path_a and /path_b both can serve 10 requests per second. The last argument, 50, indicates the maximum number of keys that the throttler will keep in memory.

MemStats

The MemStats function creates a throttler that allows requests to go through only if the memory statistics of the current process are below specified thresholds.

For example:

th := throttled.MemStats(throttled.MemThresholds(&runtime.MemStats{NumGC: 10}, 10*time.Millisecond)
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will allow requests to go through until the number of garbage collections reaches the initial number + 10 (the MemThresholds function creates absolute memory stats thresholds from offsets). The second argument, 10ms, indicates the refresh rate of the memory stats.

RateLimit

The RateLimit function creates a throttler that allows a certain number of requests in a given time window, as is often implemented in public RESTful APIs.

For example:

th := throttled.RateLimit(throttled.PerMin(30), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(1000))
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will limit requests to 30 per minute, based on the remote address of the client, and will store the counter and remaining time of the current window in the provided memory store, limiting the number of keys to keep in memory to 1000. The store sub-package also provides a Redis-based Store implementations.

The RateLimit throttler sets the expected X-RateLimit-* headers on the response, and also sets a Retry-After header when the limit is exceeded.

Documentation

The API documentation is available as usual on godoc.org.

There is also a blog post explaining the package's usage on 0value.com.

Finally, many examples are provided in the /examples sub-folder of the repository.

License

The BSD 3-clause license. Copyright (c) 2014 Martin Angers and Contributors.

Documentation

Overview

Package throttled implements different throttling strategies for controlling access to HTTP handlers.

Installation

go get gopkg.in/throttled/throttled.v1/...

Inverval

The Interval function creates a throttler that allows requests to go through at a controlled, constant interval. The interval may be applied to all requests (vary argument == nil) or independently based on vary-by criteria.

For example:

th := throttled.Interval(throttled.PerSec(10), 100, &throttled.VaryBy{Path: true}, 50)
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will allow a request each 100ms (10 requests per second), with a buffer of 100 exceeding requests before dropping requests with a status code 429 (by default, configurable using th.DeniedHandler or the package-global DefaultDeniedHandler variable). Different paths will be throttled independently, so that /path_a and /path_b both can serve 10 requests per second. The last argument, 50, indicates the maximum number of keys that the throttler will keep in memory.

MemStats

The MemStats function creates a throttler that allows requests to go through only if the memory statistics of the current process are below specified thresholds.

For example:

th := throttled.MemStats(throttled.MemThresholds(&runtime.MemStats{NumGC: 10}, 10*time.Millisecond)
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will allow requests to go through until the number of garbage collections reaches the initial number + 10 (the MemThresholds function creates absolute memory stats thresholds from offsets). The second argument, 10ms, indicates the refresh rate of the memory stats.

RateLimit

The RateLimit function creates a throttler that allows a certain number of requests in a given time window, as is often implemented in public RESTful APIs.

For example:

th := throttled.RateLimit(throttled.PerMin(30), &throttled.VaryBy{RemoteAddr: true}, store.NewMemStore(1000))
h := th.Throttle(myHandler)
http.ListenAndServe(":9000", h)

Creates a throttler that will limit requests to 30 per minute, based on the remote address of the client, and will store the counter and remaining time of the current window in the provided memory store, limiting the number of keys to keep in memory to 1000. The store sub-package also provides a Redis-based Store implementations.

The RateLimit throttler sets the expected X-RateLimit-* headers on the response, and also sets a Retry-After header when the limit is exceeded.

Documentation

The API documentation is available as usual on godoc.org:

http://godoc.org/gopkg.in/throttled/throttled.v1

There is also a blog post explaining the package's usage on 0value.com:

http://0value.com/throttled--guardian-of-the-web-server

Finally, many examples are provided in the /examples sub-folder of the repository.

License

The BSD 3-clause license. Copyright (c) 2014 Martin Angers and Contributors.

http://opensource.org/licenses/BSD-3-Clause

Index

Constants

This section is empty.

Variables

View Source
var (
	// DefaultDeniedHandler handles the requests that were denied access because
	// of a throttler. By default, returns a 429 status code with a
	// generic message.
	DefaultDeniedHandler = http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "limit exceeded", 429)
	}))

	// Error is the function to call when an error occurs on a throttled handler.
	// By default, returns a 500 status code with a generic message.
	Error = ErrorFunc(func(w http.ResponseWriter, r *http.Request, err error) {
		http.Error(w, "internal error", http.StatusInternalServerError)
	})
)
View Source
var ErrNoSuchKey = errors.New("throttled: no such key")

The error returned if the key does not exist in the Store.

Functions

func MemThresholds

func MemThresholds(offset *runtime.MemStats) *runtime.MemStats

MemThresholds is a convenience function to create a thresholds memory stats from offsets to apply to the current memory stats. Zero values in the offset stats are left to 0 in the resulting thresholds memory stats value.

The return value may be used as thresholds argument to the MemStats function.

func RemainingSeconds

func RemainingSeconds(ts time.Time, window time.Duration) int

RemainingSeconds is a helper function that returns the number of seconds remaining from an absolute timestamp in UTC.

Types

type D

type D time.Duration

D represents a custom delay.

func (D) Delay

func (d D) Delay() time.Duration

Delay returns the duration to wait before the next request can go through, which is the custom duration represented by the D value.

type Delayer

type Delayer interface {
	// Delay returns a duration.
	Delay() time.Duration
}

The Delayer interface defines the method to implement to describe a delay as required by the Interval throttler.

type ErrorFunc

type ErrorFunc func(w http.ResponseWriter, r *http.Request, err error)

ErrorFunc defines the function type for the Error variable.

type Limiter

type Limiter interface {
	Start()
	Limit(http.ResponseWriter, *http.Request) (<-chan bool, error)
}

The Limiter interface defines the methods required to control access to a throttled handler.

type PerDay

type PerDay int

PerDay represents a number of requests per day.

func (PerDay) Delay

func (pd PerDay) Delay() time.Duration

Delay returns the duration to wait before the next request can go through, so that PerDay(n) == n requests per day at regular intervals.

func (PerDay) Quota

func (pd PerDay) Quota() (int, time.Duration)

Quota returns the number of requests allowed in a 1 day time window, so that PerDay(n) == n requests allowed per day.

type PerHour

type PerHour int

PerHour represents a number of requests per hour.

func (PerHour) Delay

func (ph PerHour) Delay() time.Duration

Delay returns the duration to wait before the next request can go through, so that PerHour(n) == n requests per hour at regular intervals.

func (PerHour) Quota

func (ph PerHour) Quota() (int, time.Duration)

Quota returns the number of requests allowed in a 1 hour time window, so that PerHour(n) == n requests allowed per hour.

type PerMin

type PerMin int

PerMin represents a number of requests per minute.

func (PerMin) Delay

func (pm PerMin) Delay() time.Duration

Delay returns the duration to wait before the next request can go through, so that PerMin(n) == n requests per minute at regular intervals.

func (PerMin) Quota

func (pm PerMin) Quota() (int, time.Duration)

Quota returns the number of requests allowed in a 1 minute time window, so that PerMin(n) == n requests allowed per minute.

type PerSec

type PerSec int

PerSec represents a number of requests per second.

func (PerSec) Delay

func (ps PerSec) Delay() time.Duration

Delay returns the duration to wait before the next request can go through, so that PerSec(n) == n requests per second at regular intervals.

func (PerSec) Quota

func (ps PerSec) Quota() (int, time.Duration)

Quota returns the number of requests allowed in a 1 second time window, so that PerSec(n) == n requests allowed per second.

type Q

type Q struct {
	Requests int
	Window   time.Duration
}

Q represents a custom quota.

func (Q) Quota

func (q Q) Quota() (int, time.Duration)

Quota returns the number of requests allowed and the custom time window.

type Quota

type Quota interface {
	// Quota returns a number of requests allowed, and a duration.
	Quota() (int, time.Duration)
}

The Quota interface defines the method to implement to describe a time-window quota, as required by the RateLimit throttler.

type Store

type Store interface {
	// Incr increments the count for the specified key and returns the new value along
	// with the number of seconds remaining. It may return an error
	// if the operation fails.
	//
	// The method may return ErrNoSuchKey if the key to increment does not exist,
	// in which case Reset will be called to initialize the value.
	Incr(string, time.Duration) (int, int, error)

	// Reset resets the key to 1 with the specified window duration. It must create the
	// key if it doesn't exist. It returns an error if it fails.
	Reset(string, time.Duration) error
}

Store is the interface to implement to store the RateLimit state (number of requests per key, time-to-live or creation timestamp).

type Throttler

type Throttler struct {
	// DeniedHandler is called if the request is disallowed. If it is nil,
	// the DefaultDeniedHandler variable is used.
	DeniedHandler http.Handler
	// contains filtered or unexported fields
}

A Throttler controls access to HTTP handlers using a Limiter.

func Custom

func Custom(l Limiter) *Throttler

Custom creates a Throttler using the provided Limiter implementation.

func Interval

func Interval(delay Delayer, bursts int, vary *VaryBy, maxKeys int) *Throttler

Interval creates a throttler that controls the requests so that they go through at a constant interval. The interval is specified by the delay argument, and convenience types such as PerSec can be used to express the interval in a more expressive way, i.e. PerSec(10) means 10 requests per second or one request each 100ms, PerMin(30) means 30 requests per minute or on request each 2s, etc.

The bursts argument indicates the number of exceeding requests that may be queued up waiting to be processed. Requests that overflow the queue are dropped and go through the denied handler, which may be specified on the Throttler and that defaults to the package-global variable DefaultDeniedHandler.

The vary argument indicates the criteria to use to group the requests, so that the interval applies to the requests in the same group (e.g. based on the path, or the remote IP address, etc.). If this argument is nil, the interval applies to all requests going through this throttler.

The maxKeys indicates the maximum number of keys to keep in memory to apply the interval, when a vary argument is specified. A LRU algorithm is used to remove older keys.

func MemStats

func MemStats(thresholds *runtime.MemStats, refreshRate time.Duration) *Throttler

MemStats creates a Throttler based on the memory statistics of the current process. Any combination of any (non-array) integer field of Go's runtime.MemStats structure can be used as thresholds to deny a request.

As soon as one threshold value is reached, the access is denied. If the value can decrease, access will be allowed again once it gets back under the threshold value. Denied requests go through the denied handler, which may be specified on the Throttler and that defaults to the package-global variable DefaultDeniedHandler.

Thresholds must be specified in absolute numbers (i.e. NumGC = 10 means stop once the NumGC reaches 10, not when the current value increments by 10), and zero values are ignored.

The refreshRate indicates the frequency at which the process' memory stats are refreshed, and 0 means on each request.

func RateLimit

func RateLimit(q Quota, vary *VaryBy, store Store) *Throttler

RateLimit creates a throttler that limits the number of requests allowed in a certain time window defined by the Quota q. The q parameter specifies the requests per time window, and it is silently set to at least 1 request and at least a 1 second window if it is less than that. The time window starts when the first request is made outside an existing window. Fractions of seconds are not supported, they are truncated.

The vary parameter indicates what criteria should be used to group requests for which the limit must be applied (ex.: rate limit based on the remote address). See varyby.go for the various options.

The specified store is used to keep track of the request count and the time remaining in the window. The throttled package comes with some stores in the throttled/store package. Custom stores can be created too, by implementing the Store interface.

Requests that bust the rate limit are denied access and go through the denied handler, which may be specified on the Throttler and that defaults to the package-global variable DefaultDeniedHandler.

The rate limit throttler sets the following headers on the response:

X-RateLimit-Limit : quota
X-RateLimit-Remaining : number of requests remaining in the current window
X-RateLimit-Reset : seconds before a new window

Additionally, if the request was denied access, the following header is added:

Retry-After : seconds before the caller should retry

func (*Throttler) Throttle

func (t *Throttler) Throttle(h http.Handler) http.Handler

Throttle wraps a HTTP handler so that its access is controlled by the Throttler. It returns the Handler with the throttling logic.

type VaryBy

type VaryBy struct {
	// Vary by the RemoteAddr as specified by the net/http.Request field.
	RemoteAddr bool

	// Vary by the HTTP Method as specified by the net/http.Request field.
	Method bool

	// Vary by the URL's Path as specified by the Path field of the net/http.Request
	// URL field.
	Path bool

	// Vary by this list of header names, read from the net/http.Request Header field.
	Headers []string

	// Vary by this list of parameters, read from the net/http.Request FormValue method.
	Params []string

	// Vary by this list of cookie names, read from the net/http.Request Cookie method.
	Cookies []string

	// Use this separator string to concatenate the various criteria of the VaryBy struct.
	// Defaults to a newline character if empty (\n).
	Separator string

	// Custom specifies the custom-generated key to use for this request.
	// If not nil, the value returned by this function is used instead of any
	// VaryBy criteria.
	Custom func(r *http.Request) string
}

VaryBy defines the criteria to use to group requests.

func (*VaryBy) Key

func (vb *VaryBy) Key(r *http.Request) string

Key returns the key for this request based on the criteria defined by the VaryBy struct.

Directories

Path Synopsis
examples
Package store offers a memory-based and a Redis-based throttled.Store implementation.
Package store offers a memory-based and a Redis-based throttled.Store implementation.

Jump to

Keyboard shortcuts

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