apitok

package
v0.0.0-...-589bc69 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2018 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package apitok implements rate limiting api calls based on tokens/ips

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(secret []byte) string

New returns an api token, signed with the given secret

Types

type RateLimitMem

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

RateLimitMem is an implementation of RateLimitStore which keeps all data in memory protected by a mutex

func NewRateLimitMem

func NewRateLimitMem() *RateLimitMem

NewRateLimitMem returns a new RateLimitMem, ready to be used as a RateLimitStore

func (*RateLimitMem) Clean

func (m *RateLimitMem) Clean(staleTimeout time.Duration)

Clean is an implementation of Clean for RateLimitStore

func (*RateLimitMem) DecrBy

func (m *RateLimitMem) DecrBy(key string, amount int64) int64

DecrBy is an implementation of DecrBy for RateLimitStore

func (*RateLimitMem) Get

func (m *RateLimitMem) Get(key string) int64

Get is an implementation of Get for RateLimitStore

func (*RateLimitMem) IncrByCeil

func (m *RateLimitMem) IncrByCeil(key string, amount, max int64) (int64, bool)

IncrByCeil is an implementation of IncrByCeil for RateLimitStore

func (*RateLimitMem) LastModified

func (m *RateLimitMem) LastModified(key string) time.Time

LastModified is an implementation of LastModified for RateLimitStore

type RateLimitStore

type RateLimitStore interface {

	// Increments the given key by the given amount, and returns the value of
	// the key after the increment. If the key would go over the max value given
	// it should be instead set to that max (and have that max returned). True
	// should be returned in this case as well. The key should be assumed to be
	// 0 if it didn't previously exist
	IncrByCeil(key string, amount, max int64) (int64, bool)

	// Decrements the given key by the given amount, and returns the value of
	// the key after the decrement. The key should be assumed to be 0 if it
	// didn't previously exist
	DecrBy(key string, amount int64) int64

	// Retrieve the value of the given key. The key should be assumed to be 0 if
	// it didn't previously exists
	Get(key string) int64

	// The time the key was last modified. Returns the zero time if the key did
	// not previously exist
	LastModified(key string) time.Time

	// Will be called once a minute, and should be used to atomically clean up
	// any data which hasn't been modified in more than the given duration. If
	// the backing storage method has a different way of implicitely cleaning up
	// data (e.g. redis' EXPIRE command) than this may do nothing
	Clean(time.Duration)
}

RateLimitStore is used to store data needed for rate limiting. All methods must be thread-safe with each other

type RateLimiter

type RateLimiter struct {

	// The maximum time available per api token. Default is 30 seconds
	Capacity time.Duration

	// How often time is added to each bucket. Default is 5 seconds
	Interval time.Duration

	// How much time is added to each bucket every Interval. Default is 5
	// seconds
	PerInterval time.Duration

	// Where to actually store data pertaining to the RateLimiter. Default is
	// a new instance of RateLimitMem (which stores all data in memory)
	Backend RateLimitStore
}

RateLimiter implements a token bucket rate limiting system on a per-api-token basis, except instead of tokens in the bucket we instead use time. When a request is made it's first checked if the bucket is empty, if so the request is rejected. When the request is completed the time it took to complete is removed from the bucket (the bucket may have negative time in it)

At intervals new time is added to the bucket, up to a specified maximum capacity. This system has a few nice qualities:

  • Bursts of load are allowed, but not sustained load
  • Load is determined by actual time per request, so the system can't be easily gamed by making high cost requests.
  • It's pretty cheap and easy to implement

func NewRateLimiter

func NewRateLimiter() *RateLimiter

NewRateLimiter returns a new RateLimiter initialized with all default values. The fields can be changed to the desired values before the RateLimiter starts being used

func (*RateLimiter) CanUse

func (r *RateLimiter) CanUse(token string, secret []byte) UseResult

CanUse attempts to use the given api token (calling sig.Verify on it first). May return any of the UseResults

func (*RateLimiter) CanUseRaw

func (r *RateLimiter) CanUseRaw(identifier string) UseResult

CanUseRaw checks if you can "use" the given identifier, which could be anything, checking that it has a non-zero amount of time in its bucket first. Will either return Success or RateLimited

func (*RateLimiter) Use

func (r *RateLimiter) Use(identifier string, toRemove time.Duration)

Use removes the given amount of time for the identifier. Assumes that the identifier is legitimate.

type UseResult

type UseResult int

UseResult describes each of the outcomes that can occur when calling CanUse() or CanUseRaw()

const (
	// Success means that the token can be used (the bucket for it isn't empty)
	Success UseResult = iota

	// TokenInvalid means that the token isn't a valid token
	TokenInvalid

	// RateLimited means that the token can't be used because its bucket is
	// empty
	RateLimited
)

Jump to

Keyboard shortcuts

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