reqlimit

package module
v0.0.0-...-9f76e8a Latest Latest
Warning

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

Go to latest
Published: Feb 17, 2015 License: MIT Imports: 5 Imported by: 0

README

go-reqlimit

go-reqlimit is a request limiter that limit the number of request per ip address. It use redis as storage system.

Usage

  • Get the code go get github.com/donnpebe/go-reqlimit

  • Import it

import "github.com/donnpebe/go-reqlimit"
  • Use it in your code (create new ReqConfig and then create a new ReqLimiter)
// It will assume that you have redis installed in localhost port 6379 and doesn't have a password 
rq := reqlimit.New()
// or if you want complete control of your redis connection
// rq := reqlimit.New("Namespace", "localhost:6379", "redispass", 25)
defer rq.Close()

// limiter with name "rps" and rate: 10req/second
rps := rq.NewLimiter("rps", 1, 10)
// you can have more than one limiter
// this limiter has name "rpm" and rate: 30req/minute
// name of limiter must be unique, or it will panic
rpm := rq.NewLimiter("rpm", 60, 30)

// test if request exceed the limit with Exceed method
// where r is *http.Request
sok, _ := rps.Exceed(r)
mok, _ := rpm.Exceed(r)
if sok || mok {
	http.Error(w, "Request limit exceeded", http.StatusForbidden)
}

Disclaimer

The code in this repo is a toy project and has not been fully tested. I will improve it later. Use at your own risk.

Example

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"

	"github.com/donnpebe/go-reqlimit"
)

const (
	namespace = "Appname"
	redishost = "localhost:6379"
	redispass = "cr4b"
	redispool = 25
)

var rpm *reqlimit.ReqLimiter

func requestLimiter(h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		exc, err := rpm.Exceed(r)
		if err != nil {
			log.Printf("Error: %v\n", err)
			http.Error(w, "Something went wrong", http.StatusInternalServerError)
			return
		}

		if exc {
			http.Error(w, "Request limit exceeded", http.StatusForbidden)
			return
		}
		h(w, r)
	}
}

func main() {
	rq := reqlimit.New(namespace, redishost, redispass, redispool)
	defer rq.Close()

	rpm = rq.NewLimiter("rps", 60, 20)
	http.HandleFunc("/limit", requestLimiter(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello and welcome to %q", html.EscapeString(r.URL.Path))
	}))
	log.Fatal(http.ListenAndServe(":8080", nil))
}

License

MIT Public License

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ReqConfig

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

ReqConfig control the reqlimit general configuration

func New

func New(attrs ...interface{}) *ReqConfig

New create a new ReqLimiter Use it like this: New(namespace, redisHost, redisPass, redisPoolCount) namespace: namespace for redis key (optional, default empty) redisHost: redis host and port (optional, default localhost:6379) redisPass: redis password (optional, default empty) redisPoolCount: number of pool for redis connection (optional, default 5)

func (*ReqConfig) Close

func (rc *ReqConfig) Close()

Close close the connection use by reqlimiter, you must call this close after you done using req limiter

func (*ReqConfig) NewLimiter

func (rc *ReqConfig) NewLimiter(name string, interval int, limit int) *ReqLimiter

NewLimiter create request limiter for limit/interval (ex 20/second) interval must be in second you can make more than one limiter but name of limiter must be unique if there is duplicate in names, it will panic

type ReqLimiter

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

ReqLimiter limit how many request can be made per interval Duration

func (*ReqLimiter) Exceed

func (rl *ReqLimiter) Exceed(r *http.Request) (bool, error)

Exceed return true if request exceeded the limit, false otherwise

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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