throttle

package module
v0.0.0-...-0dc5a8e Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2020 License: MIT Imports: 9 Imported by: 8

README

throttle wercker status

Simple throttling for martini, negroni or Macaron.

API Reference

Description

Package throttle provides quota-based throttling.

Policy

throttle.Policy is a middleware that allows you to throttle by the given quota.

Quota

throttle.Quota is a quota type with a limit and a duration

Usage

This package provides a way to install rate limit or interval policies for throttling:

m := martini.Classic()

// A Rate Limit Policy
m.Use(throttle.Policy(&throttle.Quota{
	Limit: 1000,
	Within: time.Hour,
}))

// An Interval Policy
m.Use(throttle.Policy(&throttle.Quota{
	Limit: 1,
	Within: time.Second,
}))

m.Any("/test", func() int {
	return http.StatusOK
})

// A Policy local to a given route
adminPolicy := Policy(&throttle.Quota{
	Limit: 100,
	Within: time.Hour,
})

m.Get("/admin", adminPolicy, func() int {
	return http.StatusOK
})

...

Options

You can configure the options for throttling by passing in throttle.Options as the second argument to throttle.Policy. Use it to configure the following options (defaults are used here):

&throttle.Options{
	// The Status Code returned when the client exceeds the quota. Defaults to 429 Too Many Requests
	StatusCode int

	// The response body returned when the client exceeds the quota
	Message string

	// A function to identify a request, must satisfy the interface func(*http.Request)string
	// Defaults to a function identifying the request by IP or X-Forwarded-For Header if provided
	// So if you want to identify by an API key given in request headers or something else, configure this option
	IdentificationFunction func(*http.Request) string

	// The key prefix to use in any key value store
	KeyPrefix string

	// The store to use. The key value store has to satisfy the throttle.KeyValueStorer interface
	// For further explanation, see below
	Store KeyValueStorer

	// If the throttle is disabled or not
	// defaults to false
	Disabled bool
}

State Storage

Throttling relies on storage of one key per Policy and user in a (KeyValue) Storage. The interface the store has to satisfy is throttle.KeyValueStorer, or, more explicit:

type KeyValueStorer interface {
	Get(key string) ([]byte, error)
	Set(key string, value []byte) error
}

This allows for drop in replacement of the store with most common go libraries for key value stores like redis.go

var client redis.Client

m.Use(throttle.Policy(&throttle.Quota{
	Limit: 10,
	Within: time.Minute,
}, &throttle.Options{
	Store: &client,
}))

Adapters are also very easy to write. throttle prefixes every key, your adapter does not have to care about it, and the stored value is stringified JSON.

The default state storage is in memory via a concurrent-safe map[string][]byte cleaning up every 15 minutes. While this works fine for clients running one instance of a martini server, for all other uses you should obviously opt for a proper key value store.

Headers & Status Codes

throttle adds the following X-RateLimit-*-Headers to every response it controls:

  • X-RateLimit-Limit: The maximum number of requests that the consumer is permitted to make within the given time window
  • X-RateLimit-Remaining: The number of requests remaining in the current rate limit window
  • X-RateLimit-Reset: The time at which the current rate limit window resets in UTC epoch seconds

No Retry-After Header is added to the response, since the X-RateLimit-Reset makes it redundant. Also it is not recommended to use a 503 Service Unavailable Status Code when Limiting the rate of requests, since the 5xx Status Code Family indicates an error on the servers side.

Authors

Documentation

Index

Constants

View Source
const (
	// Too Many Requests According to http://tools.ietf.org/html/rfc6585#page-3
	StatusTooManyRequests = 429
)

Variables

This section is empty.

Functions

func Policy

func Policy(quota *Quota, options ...*Options) func(resp http.ResponseWriter, req *http.Request)

A throttling Policy Takes two arguments, one required: First is a Quota (A Limit with an associated time). When the given Limit of requests is reached by a user within the given time window, access to access to resources will be denied to this user Second is Options to use with this policy. For further information on options, see Options further above.

Types

type FreshnessInformer

type FreshnessInformer interface {
	IsFresh() bool
}

type KeyValueStorer

type KeyValueStorer interface {
	// Simple Get Function
	Get(key string) ([]byte, error)
	// Simple Set Function
	Set(key string, value []byte) error
}

KeyValueStorer is the required interface for the Store Option This should allow for either drop-in replacement with compatible libraries, or easy write-up of adapters

type MapStore

type MapStore struct {
	*sync.RWMutex
	// contains filtered or unexported fields
}

A very simple implementation of a key value store (a concurrent safe map)

func NewMapStore

func NewMapStore(binding FreshnessInformer, options ...*MapStoreOptions) *MapStore

Returns a simple key value store

func (*MapStore) Clean

func (s *MapStore) Clean()

Clean the store from expired values

func (*MapStore) CleanEvery

func (s *MapStore) CleanEvery(cleaningPeriod time.Duration)

Simple cleanup mechanism, cleaning the store every 15 minutes

func (*MapStore) Delete

func (s *MapStore) Delete(key string)

Delete a key

func (*MapStore) Get

func (s *MapStore) Get(key string) (value []byte, err error)

Get a key, will return an error if the key does not exist

func (*MapStore) Read

func (s *MapStore) Read(key string) (FreshnessInformer, error)

Read the data into the given binding

func (*MapStore) Set

func (s *MapStore) Set(key string, value []byte) error

Set a key

type MapStoreError

type MapStoreError string

Error Type for the key value store

func (MapStoreError) Error

func (err MapStoreError) Error() string

The Error for Key Value Store

type MapStoreOptions

type MapStoreOptions struct {
	// The period to clean the store in
	CleaningPeriod time.Duration
}

type Options

type Options struct {
	// The status code to be returned for throttled requests
	// Defaults to 429 Too Many Requests
	StatusCode int

	// The message to be returned as the body of throttled requests
	Message string

	// The function used to identify the requester
	// Defaults to IP identification
	IdentificationFunction func(*http.Request) string

	// The key prefix to use in any key value store
	// defaults to "throttle"
	KeyPrefix string

	// The store to use
	// defaults to a simple concurrent-safe map[string]string
	Store KeyValueStorer

	// If the throttle is disabled or not
	// defaults to false
	Disabled bool
}

func (*Options) Identify

func (o *Options) Identify(req *http.Request) string

Identify via the given Identification Function

type Quota

type Quota struct {
	// The Request Limit
	Limit uint64
	// The time window for the request Limit
	Within time.Duration
}

The Quota is Request Rates per Time for a given policy

func (*Quota) KeyId

func (q *Quota) KeyId() string

Jump to

Keyboard shortcuts

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