redis_rate

package module
v6.4.0+incompatible Latest Latest
Warning

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

Go to latest
Published: May 10, 2017 License: BSD-2-Clause Imports: 4 Imported by: 0

README

Rate limiting for go-redis

Build Status

package main

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
    "time"

    "golang.org/x/time/rate"
    "github.com/go-redis/redis_rate"
    "github.com/go-redis/redis"
)

func handler(w http.ResponseWriter, req *http.Request, rateLimiter *redis_rate.Limiter) {
    userID := "user-12345"
    limit := int64(5)

    rate, reset, allowed := rateLimiter.AllowMinute(userID, limit)
    if !allowed {
        w.Header().Set("X-RateLimit-Limit", strconv.FormatInt(limit, 10))
        w.Header().Set("X-RateLimit-Remaining", strconv.FormatInt(limit-rate, 10))
        w.Header().Set("X-RateLimit-Reset", strconv.FormatInt(reset, 10))
        http.Error(w, "API rate limit exceeded.", 429)
        return
    }

    fmt.Fprintf(w, "Hello world!\n")
    fmt.Fprint(w, "Rate limit remaining: ", strconv.FormatInt(limit-rate, 10))
}

func statusHandler(w http.ResponseWriter, req *http.Request, rateLimiter *redis_rate.Limiter) {
    userID := "user-12345"
    limit := int64(5)

    // With n=0 we just retrieve the current limit.
    rate, reset, allowed := rateLimiter.AllowN(userID, limit, time.Minute, 0)
    fmt.Fprintf(w, "Current rate: %d", rate)
    fmt.Fprintf(w, "Reset: %d", reset)
    fmt.Fprintf(w, "Allowed: %v", allowed)
}

func main() {
    ring := redis.NewRing(&redis.RingOptions{
        Addrs: map[string]string{
            "server1": "localhost:6379",
        },
    })
    limiter := rate.NewLimiter(ring)
    // Optional.
    limiter.Fallback = timerate.NewLimiter(rate.Every(time.Second), 100)

    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        handler(w, req, limiter)
    })

    http.HandleFunc("/status", func(w http.ResponseWriter, req *http.Request) {
        statusHandler(w, req, limiter)
    })

    http.HandleFunc("/favicon.ico", http.NotFound)
    log.Println("listening on localhost:8888...")
    log.Println(http.ListenAndServe("localhost:8888", nil))
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Limiter

type Limiter struct {

	// Optional fallback limiter used when Redis is unavailable.
	Fallback *rate.Limiter
	// contains filtered or unexported fields
}

Limiter controls how frequently events are allowed to happen.

func NewLimiter

func NewLimiter(redis rediser) *Limiter

func (*Limiter) Allow

func (l *Limiter) Allow(name string, maxn int64, dur time.Duration) (count, reset int64, allow bool)

Allow is shorthand for AllowN(name, max, dur, 1).

func (*Limiter) AllowHour

func (l *Limiter) AllowHour(name string, maxn int64) (int64, int64, bool)

AllowHour is shorthand for Allow(name, maxn, time.Hour).

func (*Limiter) AllowMinute

func (l *Limiter) AllowMinute(name string, maxn int64) (int64, int64, bool)

AllowMinute is shorthand for Allow(name, maxn, time.Minute).

func (*Limiter) AllowN

func (l *Limiter) AllowN(name string, maxn int64, dur time.Duration, n int64) (count, reset int64, allow bool)

AllowN reports whether an event with given name may happen at time now. It allows up to maxn events within duration dur, with each interaction incrementing the limit by n.

func (*Limiter) AllowRate

func (l *Limiter) AllowRate(name string, rateLimit rate.Limit) (delay time.Duration, allow bool)

AllowRate reports whether an event may happen at time now. It allows up to rateLimit events each second.

func (*Limiter) Reset

func (l *Limiter) Reset(name string, dur time.Duration) error

Reset resets the rate limit for the name in the given rate limit window.

func (*Limiter) ResetRate

func (l *Limiter) ResetRate(name string, rateLimit rate.Limit) error

Reset resets the rate limit for the name and limit.

Jump to

Keyboard shortcuts

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