Help us shape the future of Go! Take the 2026 Go Developer Survey

ratelimit

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package ratelimit limits requests per key (token, user, IP) with GCRA, a smooth token bucket that needs one timestamp per key. The memory store fits one process; drivers/redis provides a shared one (BETA).

Middleware applies a Limiter (NewMemory or the Redis one) to a route, keyed by a KeyFunc such as ByIP or ByToken; it sets the RateLimit-* headers, answers 429 with Retry-After and denies when the limiter fails.

See https://github.com/AlexGalhardo/vukem/blob/main/docs/subsystems.md.

Example
package main

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

	"github.com/AlexGalhardo/vukem/ratelimit"
)

func main() {
	limiter := ratelimit.NewMemory(2, time.Minute)
	h := ratelimit.Middleware(limiter, ratelimit.ByIP)(
		http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusNoContent)
		}),
	)

	for range 3 {
		req := httptest.NewRequest(http.MethodGet, "/api/posts", http.NoBody)
		rec := httptest.NewRecorder()
		h.ServeHTTP(rec, req)
		fmt.Println(rec.Code, rec.Header().Get("RateLimit-Remaining"))
	}
}
Output:
204 1
204 0
429 0

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ByIP

func ByIP(r *http.Request) string

ByIP keys requests by client IP (honouring trusted proxies).

func ByToken

func ByToken(r *http.Request) string

ByToken keys requests by bearer token (hashed, never stored in clear), falling back to the client IP. Use it after authentication (auth.Required), behind an IP limit: before the token is verified, a client rotating made-up tokens gets a fresh bucket on every request.

func Middleware

func Middleware(l Limiter, key KeyFunc) func(http.Handler) http.Handler

Middleware limits requests with l, keyed by key (ByIP when nil). It sets RateLimit-Limit/Remaining/Reset on every response and answers 429 with Retry-After when the bucket is empty. A failing limiter denies the request (fail closed).

Types

type KeyFunc

type KeyFunc func(r *http.Request) string

KeyFunc picks the bucket for a request; "" skips limiting.

type Limiter

type Limiter interface {
	Allow(ctx context.Context, key string) (Result, error)
}

Limiter decides whether a request for key may proceed.

type Memory

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

Memory is an in-process GCRA limiter: limit requests per window, with bursts up to limit.

func NewMemory

func NewMemory(limit int, window time.Duration) *Memory

NewMemory allows limit requests per window for each key.

func (*Memory) Allow

func (m *Memory) Allow(_ context.Context, key string) (Result, error)

Allow implements Limiter.

type Result

type Result struct {
	Allowed    bool
	Limit      int
	Remaining  int
	ResetAfter time.Duration // until the bucket is full again
	RetryAfter time.Duration // when denied: until the next request is allowed
}

Result is the outcome of one Allow call.

Jump to

Keyboard shortcuts

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