oakratelimiter

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2023 License: MIT Imports: 13 Imported by: 0

README

Oak Rate Limiter

Flexible HTTP rate limiter with multiple backend drivers and optional timing modulation with partial obfuscation.

Usage

package main

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/dkotik/oakratelimiter"
	"github.com/dkotik/oakratelimiter/driver/mutexrlm"
)

// see more examples in the examples directory
func main() {
  // select random port
	l, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		panic(err)
	}
	defer l.Close()

	rl, err := mutexrlm.NewRequestLimiter(mutexrlm.WithNewRate(1, time.Second))
	if err != nil {
		panic(err)
	}

	limiter, err := oakratelimiter.New(
		oakratelimiter.HandlerFunc( // Oak Handler
			func(w http.ResponseWriter, r *http.Request) error {
				_, err := io.WriteString(w, "Hello World")
				return err
			},
		),
		oakratelimiter.WithRequestLimiter("global", rl),
	)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Listening at http://%s\n", l.Addr())
	http.Serve(l, limiter)
}

Supported Backend Drivers

  • In-memory sync.Mutex map: mutexrlmrlm.New
  • Postgres: postgresrlm.New
  • SQLite: sqliterlm.New
  • (planned) Swiss map
  • Atomic
  • Redis

Bundled Request Taggers

Taggers differentiate requests based on a property. Each can be combined with a different backend driver.

  • By IP address: tagbyip.New
  • By Header: tagbyheader.New
    • Supports optional WithNoHeaderLimiter
  • By Cookie: tagbycookie.New
    • Supports optional WithNoCookieLimiter
  • By Context Value: tagbycontext.New
    • Supports optional WithNoValueLimiter

Timing Modulation

Use timing.NewTimingModulator or timing.NewMiddleware to protect endpoints from timing attacks by injecting random delays.

Documentation

Overview

Package oakratelimiter protects API endpoints with rate limiting middleware.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Error

type Error interface {
	error
	HyperTextStatusCode() int
}

type Handler

type Handler interface {
	ServeHyperText(http.ResponseWriter, *http.Request) error
}

type HandlerFunc

type HandlerFunc func(http.ResponseWriter, *http.Request) error

func (HandlerFunc) ServeHyperText

func (f HandlerFunc) ServeHyperText(w http.ResponseWriter, r *http.Request) error

type HeaderWriter

type HeaderWriter interface {
	ReportAccessAllowed(header http.Header, tokens float64)
	ReportAccessDenied(header http.Header, tokens float64)
	ReportError(header http.Header)
}

HeaderWriter reports rate limiter state.

func NewObfuscatingHeaderWriter

func NewObfuscatingHeaderWriter(displayRate *rate.Rate) HeaderWriter

NewObfuscatingHeaderWriter creates an ObfuscatingHeaderWriter using a given rate, which may differ from the actual rate.

type Middleware

type Middleware func(Handler) Handler

func NewMiddleware

func NewMiddleware(withOptions ...Option) (Middleware, error)

NewMiddleware creates a Middleware that wraps [Handler]s into a RequestHandler.

type ObfuscatingHeaderWriter

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

ObfuscatingHeaderWriter reports the rate per second regardless of the real rate.Rate interval. It can report the rate different from the actual. This is done to avoid leaking the internal state of the system, which may aid the attackers in overcoming the rate limiter.

func (*ObfuscatingHeaderWriter) ReportAccessAllowed

func (o *ObfuscatingHeaderWriter) ReportAccessAllowed(
	h http.Header,
	tokens float64,
)

ReportAccessAllowed indicates that the request was not limited.

func (*ObfuscatingHeaderWriter) ReportAccessDenied

func (o *ObfuscatingHeaderWriter) ReportAccessDenied(
	h http.Header,
	tokens float64,
)

ReportAccessDenied indicates the request was blocked due to the rate limiter.

func (*ObfuscatingHeaderWriter) ReportError

func (o *ObfuscatingHeaderWriter) ReportError(h http.Header)

ReportError writes appropriate headers for a failing rate limiter.

type Option

type Option func(*options) error

Option initializes an [OakRateLimiter] or Middleware.

func WithContextTagger

func WithContextTagger(withOptions ...tagbycontext.Option) Option

WithContextTagger configures rate limiter to track requests based on a certain context.Context value.

func WithCookieTagger

func WithCookieTagger(withOptions ...tagbycookie.Option) Option

WithCookieTagger configures rate limiter to track requests based on a certain cookie.

func WithGlobalRate

func WithGlobalRate(r *rate.Rate) Option

WithGlobalRate applies a rate.Rate without differentiating by tag.

func WithGlobalRateLimiter

func WithGlobalRateLimiter(tag string, l rate.Limiter) Option

WithGlobalRateLimiter applies a blind request.Limiter that always takens tokens from the same tag.

func WithGlobalRequestLimiter

func WithGlobalRequestLimiter(l request.Limiter) Option

WithGlobalRequestLimiter applies mutexrlm.RequestLimiter as the top request limiter named "global".

func WithHeaderTagger

func WithHeaderTagger(withOptions ...tagbyheader.Option) Option

WithHeaderTagger configures rate limiter to track requests based on a certain HTTP header.

func WithHeaderWriter

func WithHeaderWriter(h HeaderWriter) Option

WithHeaderWriter sets a HeaderWriter for RequestHandler.

func WithIPAddressTagger

func WithIPAddressTagger(
	withOptions ...tagbyip.Option,
) Option

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

func WithRequestLimiter

func WithRequestLimiter(name string, rl request.Limiter) Option

WithRequestLimiter adds a request.Limiter to the list used by RequestHandler.

type RequestHandler

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

RequestHandler applies a set of [request.Limiter]s to an http.Request.

func New

func New(next Handler, withOptions ...Option) (*RequestHandler, error)

New initializes a RequestHandler using a list of [Option]s.

func (*RequestHandler) ServeHTTP

func (rh *RequestHandler) ServeHTTP(
	w http.ResponseWriter, r *http.Request,
)

ServeHTTP satisfies http.Handler for compatibility with the standard library.

func (*RequestHandler) ServeHyperText

func (rh *RequestHandler) ServeHyperText(
	w http.ResponseWriter, r *http.Request,
) (err error)

ServeHyperText satisfies an improved http.Handler interface.

type SilentHeaderWriter

type SilentHeaderWriter struct{}

SilentHeaderWriter does not write any headers.

func (*SilentHeaderWriter) ReportAccessAllowed

func (s *SilentHeaderWriter) ReportAccessAllowed(http.Header, float64)

func (*SilentHeaderWriter) ReportAccessDenied

func (s *SilentHeaderWriter) ReportAccessDenied(http.Header, float64)

func (*SilentHeaderWriter) ReportError

func (s *SilentHeaderWriter) ReportError(http.Header)

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) HyperTextStatusCode

func (e *TooManyRequestsError) HyperTextStatusCode() int

HTTPStatusCode presents a standard HTTP status code.

func (*TooManyRequestsError) LogValue

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

LogValue captures causes into structured log entries.

Directories

Path Synopsis
driver
mutexrlm
Package mutexrlm provides [rate.Limiter]s that use memory stores with sync.Mutex for safe concurrency.
Package mutexrlm provides [rate.Limiter]s that use memory stores with sync.Mutex for safe concurrency.
swissrlm
Package swissrlm provides [oakratelimiter.RateLimiter]s that use concurrent [Swiss map] for safe concurrenct access.
Package swissrlm provides [oakratelimiter.RateLimiter]s that use concurrent [Swiss map] for safe concurrenct access.
examples
Package rate defines [Rate] and provides basic interfaces for rate limiter driver implementations.
Package rate defines [Rate] and provides basic interfaces for rate limiter driver implementations.
Package request defines and implements [Limiter] and [Tagger] for throttling [http.Request]s.
Package request defines and implements [Limiter] and [Tagger] for throttling [http.Request]s.
tagbycontext
Package tagbycontext implements [request.Limiter] by extracting values from request context.Context.
Package tagbycontext implements [request.Limiter] by extracting values from request context.Context.
tagbycookie
Package tagbycookie implements [request.Limiter] by extracting an HTTP cookie from [http.Request]s.
Package tagbycookie implements [request.Limiter] by extracting an HTTP cookie from [http.Request]s.
tagbyheader
Package tagbyheader implements [request.Limiter] by extracting an HTTP header value from [http.Request]s.
Package tagbyheader implements [request.Limiter] by extracting an HTTP header value from [http.Request]s.
tagbyip
Package tagbyip implements [request.Limiter] by extracting Internet Protocol addresses from [http.Request]s.
Package tagbyip implements [request.Limiter] by extracting Internet Protocol addresses from [http.Request]s.
Package test provides fixtures for testing [oakratelimiter.RequestLimiter] and [oakratelimiter.RateLimiter] implimentations.
Package test provides fixtures for testing [oakratelimiter.RequestLimiter] and [oakratelimiter.RateLimiter] implimentations.
Package timing provides request modulation middleware that mitigates timing attacks.
Package timing provides request modulation middleware that mitigates timing attacks.

Jump to

Keyboard shortcuts

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