httprate

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2024 License: MIT Imports: 9 Imported by: 111

README

httprate

net/http request rate limiter based on the Sliding Window Counter pattern inspired by CloudFlare https://blog.cloudflare.com/counting-things-a-lot-of-different-things/.

The sliding window counter pattern is accurate, smooths traffic and offers a simple counter design to share a rate-limit among a cluster of servers. For example, if you'd like to use redis to coordinate a rate-limit across a group of microservices you just need to implement the httprate.LimitCounter interface to support an atomic increment and get.

Example

package main

import (
  "net/http"

  "github.com/go-chi/chi/v5"
  "github.com/go-chi/chi/v5/middleware"
  "github.com/go-chi/httprate"
)

func main() {
  r := chi.NewRouter()
  r.Use(middleware.Logger)

  // Enable httprate request limiter of 100 requests per minute.
  //
  // In the code example below, rate-limiting is bound to the request IP address
  // via the LimitByIP middleware handler.
  //
  // To have a single rate-limiter for all requests, use httprate.LimitAll(..).
  //
  // Please see _example/main.go for other more, or read the library code.
  r.Use(httprate.LimitByIP(100, 1*time.Minute))

  r.Get("/", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("."))
  })

  http.ListenAndServe(":3333", r)
}

Common use cases

Rate limit by IP and URL path (aka endpoint)
  r.Use(httprate.Limit(
  	10,             // requests
  	10*time.Second, // per duration
  	httprate.WithKeyFuncs(httprate.KeyByIP, httprate.KeyByEndpoint),
  ))
Rate limit by arbitrary keys
  r.Use(httprate.Limit(
    100,           // requests
    1*time.Minute, // per duration
    // an oversimplified example of rate limiting by a custom header
    httprate.WithKeyFuncs(func(r *http.Request) (string, error) {
    	return r.Header.Get("X-Access-Token"), nil
    }),
  ))
Send specific response for rate limited requests
  r.Use(httprate.Limit(
    10,            // requests
    1*time.Second, // per duration
    httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
      http.Error(w, "some specific response here", http.StatusTooManyRequests)
    }),
  ))

Redis backend for httprate: https://github.com/go-chi/httprate-redis

LICENSE

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func KeyByEndpoint

func KeyByEndpoint(r *http.Request) (string, error)

func KeyByIP

func KeyByIP(r *http.Request) (string, error)

func KeyByRealIP added in v0.6.0

func KeyByRealIP(r *http.Request) (string, error)

func Limit

func Limit(requestLimit int, windowLength time.Duration, options ...Option) func(next http.Handler) http.Handler

func LimitAll

func LimitAll(requestLimit int, windowLength time.Duration) func(next http.Handler) http.Handler

func LimitByIP

func LimitByIP(requestLimit int, windowLength time.Duration) func(next http.Handler) http.Handler

func LimitByRealIP added in v0.6.0

func LimitByRealIP(requestLimit int, windowLength time.Duration) func(next http.Handler) http.Handler

func LimitCounterKey

func LimitCounterKey(key string, window time.Time) uint64

func NewRateLimiter

func NewRateLimiter(requestLimit int, windowLength time.Duration, options ...Option) *rateLimiter

func WithIncrement added in v0.8.0

func WithIncrement(ctx context.Context, value int) context.Context

func WithRequestLimit added in v0.9.0

func WithRequestLimit(ctx context.Context, value int) context.Context

Types

type KeyFunc

type KeyFunc func(r *http.Request) (string, error)

type LimitCounter

type LimitCounter interface {
	Config(requestLimit int, windowLength time.Duration)
	Increment(key string, currentWindow time.Time) error
	IncrementBy(key string, currentWindow time.Time, amount int) error
	Get(key string, currentWindow, previousWindow time.Time) (int, int, error)
}

type Option

type Option func(rl *rateLimiter)

func WithKeyByIP added in v0.7.0

func WithKeyByIP() Option

func WithKeyByRealIP added in v0.7.0

func WithKeyByRealIP() Option

func WithKeyFuncs

func WithKeyFuncs(keyFuncs ...KeyFunc) Option

func WithLimitCounter

func WithLimitCounter(c LimitCounter) Option

func WithLimitHandler

func WithLimitHandler(h http.HandlerFunc) Option

func WithNoop added in v0.7.3

func WithNoop() Option

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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