ratelimit

package module
v1.6.1 Latest Latest
Warning

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

Go to latest
Published: Jan 30, 2023 License: MIT Imports: 6 Imported by: 0

README

gin-rate-limit

gin-rate-limit is a rate limiter for the gin framework. By default, it can only store rate limit info in memory and with redis. If you want to store it somewhere else you can make your own store or use third party stores. The library is new so there are no third party stores yet, so I would appreciate if someone could make one.

Install

go get github.com/USA-RedDragon/gin-rate-limit

Redis Example

package main

import (
	"github.com/USA-RedDragon/gin-rate-limit"
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"time"
)

func keyFunc(c *gin.Context) string {
	return c.ClientIP()
}

func errorHandler(c *gin.Context, info ratelimit.Info) {
	c.String(429, "Too many requests. Try again in "+time.Until(info.ResetTime).String())
}

func main() {
	server := gin.Default()
	// This makes it so each ip can only make 5 requests per second
	store := ratelimit.RedisStore(&ratelimit.RedisOptions{
		RedisClient: redis.NewClient(&redis.Options{
			Addr: "localhost:7680",
		}),
		Rate:  time.Second,
		Limit: 5,
	})
	mw := ratelimit.RateLimiter(store, &ratelimit.Options{
		ErrorHandler: errorHandler,
		KeyFunc: keyFunc,
    })
	server.GET("/", mw, func(c *gin.Context) {
		c.String(200, "Hello World")
	})
	server.Run(":8080")
}

Basic Setup

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/USA-RedDragon/gin-rate-limit"
	"time"
)

func keyFunc(c *gin.Context) string {
	return c.ClientIP()
}

func errorHandler(c *gin.Context, info ratelimit.Info) {
	c.String(429, "Too many requests. Try again in "+time.Until(info.ResetTime).String())
}

func main() {
	server := gin.Default()
	// This makes it so each ip can only make 5 requests per second
	store := ratelimit.InMemoryStore(&ratelimit.InMemoryOptions{
		Rate:  time.Second,
		Limit: 5,
	})
	mw := ratelimit.RateLimiter(store, &ratelimit.Options{
		ErrorHandler: errorHandler,
		KeyFunc: keyFunc,
	})
	server.GET("/", mw, func(c *gin.Context) {
		c.String(200, "Hello World")
	})
	server.Run(":8080")
}

Custom Store Example

package main

import (
	"github.com/USA-RedDragon/gin-rate-limit"
	"github.com/gin-gonic/gin"
)

type CustomStore struct {
}

// Your store must have a method called Limit that takes a key, *gin.Context and returns ratelimit.Info
func (s *CustomStore) Limit(key string, c *gin.Context) Info {
	if UserWentOverLimit {
		return Info{
			RateLimited:   true,
			ResetTime:     reset,
			RemainingHits: 0,
		}
	}
	return Info{
		RateLimited:   false,
		ResetTime:     reset,
		RemainingHits: remaining,
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RateLimiter

func RateLimiter(s Store, options *Options) gin.HandlerFunc

RateLimiter is a function to get gin.HandlerFunc

Types

type InMemoryOptions

type InMemoryOptions struct {
	// the user can make Limit amount of requests every Rate
	Rate time.Duration
	// the amount of requests that can be made every Rate
	Limit uint
	// a function that returns true if the request should not count toward the rate limit
	Skip func(*gin.Context) bool
}

type Info

type Info struct {
	RateLimited   bool
	ResetTime     time.Time
	RemainingHits uint
}

type Options

type Options struct {
	ErrorHandler func(*gin.Context, Info)
	KeyFunc      func(*gin.Context) string
	// a function that lets you check the rate limiting info and modify the response
	BeforeResponse func(c *gin.Context, info Info)
}

type RedisOptions

type RedisOptions struct {
	// the user can make Limit amount of requests every Rate
	Rate time.Duration
	// the amount of requests that can be made every Rate
	Limit       uint
	RedisClient *redis.Client
	// should gin-rate-limit panic when there is an error with redis
	PanicOnErr bool
	// a function that returns true if the request should not count toward the rate limit
	Skip func(*gin.Context) bool
}

type Store

type Store interface {
	// Limit takes in a key and *gin.Context and should return whether that key is allowed to make another request
	Limit(key string, c *gin.Context) Info
}

func InMemoryStore

func InMemoryStore(options *InMemoryOptions) Store

func RedisStore

func RedisStore(options *RedisOptions) Store

Jump to

Keyboard shortcuts

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