Dead simple rate limit middleware for Go.

Overview

Limiter

Documentation License Build Status Go Report Card

Dead simple rate limit middleware for Go.

  • Simple API
  • "Store" approach for backend
  • Redis support (but not tied too)
  • Middlewares: HTTP, FastHTTP and Gin

Installation

Using Go Modules

$ go get github.com/ulule/limiter/[email protected]

Usage

In five steps:

  • Create a limiter.Rate instance (the number of requests per period)
  • Create a limiter.Store instance (see Redis or In-Memory)
  • Create a limiter.Limiter instance that takes store and rate instances as arguments
  • Create a middleware instance using the middleware of your choice
  • Give the limiter instance to your middleware initializer

Example:

// Create a rate with the given limit (number of requests) for the given
// period (a time.Duration of your choice).
import "github.com/ulule/limiter/v3"

rate := limiter.Rate{
    Period: 1 * time.Hour,
    Limit:  1000,
}

// You can also use the simplified format "<limit>-<period>"", with the given
// periods:
//
// * "S": second
// * "M": minute
// * "H": hour
// * "D": day
//
// Examples:
//
// * 5 reqs/second: "5-S"
// * 10 reqs/minute: "10-M"
// * 1000 reqs/hour: "1000-H"
// * 2000 reqs/day: "2000-D"
//
rate, err := limiter.NewRateFromFormatted("1000-H")
if err != nil {
    panic(err)
}

// Then, create a store. Here, we use the bundled Redis store. Any store
// compliant to limiter.Store interface will do the job. The defaults are
// "limiter" as Redis key prefix and a maximum of 3 retries for the key under
// race condition.
import "github.com/ulule/limiter/v3/drivers/store/redis"

store, err := redis.NewStore(client)
if err != nil {
    panic(err)
}

// Alternatively, you can pass options to the store with the "WithOptions"
// function. For example, for Redis store:
import "github.com/ulule/limiter/v3/drivers/store/redis"

store, err := redis.NewStoreWithOptions(pool, limiter.StoreOptions{
    Prefix:   "your_own_prefix",
})
if err != nil {
    panic(err)
}

// Or use a in-memory store with a goroutine which clears expired keys.
import "github.com/ulule/limiter/v3/drivers/store/memory"

store := memory.NewStore()

// Then, create the limiter instance which takes the store and the rate as arguments.
// Now, you can give this instance to any supported middleware.
instance := limiter.New(store, rate)

// Alternatively, you can pass options to the limiter instance with several options.
instance := limiter.New(store, rate, limiter.WithTrustForwardHeader(true), limiter.WithIPv6Mask(mask))

// Finally, give the limiter instance to your middleware initializer.
import "github.com/ulule/limiter/v3/drivers/middleware/stdlib"

middleware := stdlib.NewMiddleware(instance)

See middleware examples:

How it works

The ip address of the request is used as a key in the store.

If the key does not exist in the store we set a default value with an expiration period.

You will find two stores:

  • Redis: rely on TTL and incrementing the rate limit on each request.
  • In-Memory: rely on a fork of go-cache with a goroutine to clear expired keys using a default interval.

When the limit is reached, a 429 HTTP status code is sent.

Why Yet Another Package

You could ask us: why yet another rate limit package?

Because existing packages did not suit our needs.

We tried a lot of alternatives:

  1. Throttled. This package uses the generic cell-rate algorithm. To cite the documentation: "The algorithm has been slightly modified from its usual form to support limiting with an additional quantity parameter, such as for limiting the number of bytes uploaded". It is brillant in term of algorithm but documentation is quite unclear at the moment, we don't need burst feature for now, impossible to get a correct After-Retry (when limit exceeds, we can still make a few requests, because of the max burst) and it only supports http.Handler middleware (we use Gin). Currently, we only need to return 429 and X-Ratelimit-* headers for n reqs/duration.

  2. Speedbump. Good package but maybe too lightweight. No Reset support, only one middleware for Gin framework and too Redis-coupled. We rather prefer to use a "store" approach.

  3. Tollbooth. Good one too but does both too much and too little. It limits by remote IP, path, methods, custom headers and basic auth usernames... but does not provide any Redis support (only in-memory) and a ready-to-go middleware that sets X-Ratelimit-* headers. tollbooth.LimitByRequest(limiter, r) only returns an HTTP code.

  4. ratelimit. Probably the closer to our needs but, once again, too lightweight, no middleware available and not active (last commit was in August 2014). Some parts of code (Redis) comes from this project. It should deserve much more love.

There are other many packages on GitHub but most are either too lightweight, too old (only support old Go versions) or unmaintained. So that's why we decided to create yet another one.

Contributing

Don't hesitate ;)

Issues
  • Improve the performance of the Redis store with Lua script

    Improve the performance of the Redis store with Lua script

    the performance of the Limiter Get with Redis transaction:

    BenchmarkGet-8   	    3110	    360345 ns/op
    
    

    the performance of the Limiter Get with Redis Lua script:

    BenchmarkGet-8   	    9850	    120478 ns/op
    

    it shows that Lua script would be 3x faster, the benchmark case was added in store_test.go

    opened by git-hulk 12
  • V3 with dep

    V3 with dep

    How can I use this package if I'm using dep rather than modules?

    When I run dep ensure I get these errors:

    Solving failure: No versions of github.com/ulule/limiter met constraints:
    	v3.1.0: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v3.0.0: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2.2.2: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2.2.1: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2.2.0: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2.1.0: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2.0.0: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v1.0.0: Could not introduce github.com/ulule/[email protected] due to multiple problematic subpackages:
    	Subpackage github.com/ulule/limiter/drivers/middleware/stdlib is missing. (Package is required by (root).)	Subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	master: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	dev: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v1: Could not introduce github.com/ulule/[email protected] due to multiple problematic subpackages:
    	Subpackage github.com/ulule/limiter/drivers/middleware/stdlib is missing. (Package is required by (root).)	Subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    	v2: Could not introduce github.com/ulule/[email protected], as its subpackage github.com/ulule/limiter/v3/drivers/store/redis is missing. (Package is required by (root).)
    
    opened by montanaflynn 10
  • Memory store clean command is a blocker

    Memory store clean command is a blocker

    Limiter is running on a high traffic server so while debugging some problems I saw high letancy from the store cleaner. I know that we need to remove the expired records but maybe there is a better way to do it?

    Screenshot 2020-03-27 at 8 07 56 PM

    enhancement 
    opened by gadelkareem 9
  • GetIP TrustForwardHeader varies per request

    GetIP TrustForwardHeader varies per request

    The recent change in https://github.com/ulule/limiter/blob/4499266ea10ad0d8b50b9fbf60a060cc95a96870/network.go#L17-L39 conflicts with the nature of the limiter. Since the limiter object is instantiated early before the server stats and then shared among different requests whose IPs are different. IMHO the TrustForwardHeader should vary based on how much the server trusts the IP and should not be as a config rule.

    Also the change of GetIP is not backward compatible - AKA broke my build :)

    The old signature used to be

    func GetIP(r *http.Request, trustForwardHeader bool) net.IP 
    
    opened by gadelkareem 7
  • rate limiting by IP address prefix

    rate limiting by IP address prefix

    For IPv6, it doesn't make sense to rate limit individual /128 addresses since end hosts often get a huge prefix assigned to them, making it easy to bypass rate limits. Instead, how about adding a normalization prefix (default /32 for IPv4 and /128 IPv6 to keep existing functionality)?

    It can be trivially accomplished by masking the desired number of bits for the prefix and using that as the IP key, for example:

    IPv4: 192.0.2.123 with a /24 prefix: becomes192.0.2.0 IPv6: 2001:db8:cafe:1234:beef::fafa with /48 prefix becomes 2001:db8:cafe::

    opened by ammmir 5
  • package limiter/drivers/store/common includes test flags in main binary

    package limiter/drivers/store/common includes test flags in main binary

    I'm currently using "limiter/drivers/store/memory" cache independently from also using the Limiter. It seems that because there is a "limiter/drivers/store/common/tests.go" in the common package, the testing package injects its flags into my application.

    Could this tests.go file be renamed to "common_test.go"?

    opened by justinfx 5
  • Add an option to customize the rate limiter key in gin middleware

    Add an option to customize the rate limiter key in gin middleware

    The user of the library can set the way the rate limiter key is computed by passing a function taking the gin context as input. We keep the current behavior by default by providing a function returning the Client IP address as a default key getter.

    opened by nbarbey 5
  • Concurrency issues in memory store

    Concurrency issues in memory store

    Noticed when reviewing the code in store_memory.go that it retrieved the cache item checked if it expired and then attempted to increment it but there was no mutex or anything to protect that.

    So it's possible that we check that it hasn't expired but by the time we IncrementInt64 it has expired and is not in the cache resulting in an error:

    item, found := s.Cache.Items()[key]
        ms := int64(time.Millisecond)
        now := time.Now()
    
           // ** TIME A: HAS NOT EXPIRED YET
        if !found || item.Expired() {
            s.Cache.Set(key, int64(1), rate.Period)
    
            return Context{
                Limit:     rate.Limit,
                Remaining: rate.Limit - 1,
                Reset:     (now.UnixNano()/ms + int64(rate.Period)/ms) / 1000,
                Reached:   false,
            }, nil
        }
    
            // ** TIME B: key has expired so this will return an error
        count, err := s.Cache.IncrementInt64(key, 1)
        if err != nil {
            return ctx, err
        }
    

    This is a little bit of an edge case, but it does result in unexpected behavior in a high concurrency environment.

    Here's a unit test spawning a bunch of goroutines resulting in an error:

    • https://github.com/dougnukem/limiter/tree/concurrency_issue
    func TestConcurrency(t *testing.T) {
        rate := Rate{Period: time.Nanosecond * 10, Limit: 100000}
    
        store := NewMemoryStoreWithOptions(StoreOptions{
            Prefix:          "limitertests:memory",
            CleanUpInterval: 1 * time.Nanosecond,
        })
    
        wg := sync.WaitGroup{}
        limiter := NewLimiter(store, rate)
        for i := 0; i < 1000; i++ {
            wg.Add(1)
            go func(i int) {
                for j := 0; j < 10000; j++ {
                    _, err := limiter.Get("boo2")
                    assert.NoError(t, err)
                }
                wg.Done()
            }(i)
        }
        wg.Wait()
    }
    
            Error Trace:    2:
        Error:      No error is expected but got Item limitertests:memory:boo2 not found
    
            Error Trace:    2:
        Error:      No error is expected but got Item limitertests:memory:boo2 not found
    
    opened by dougnukem 5
  • setRate function refresh the key expire time when the key exist?

    setRate function refresh the key expire time when the key exist?

    hi, i have a question, this function below in store_redis.go

      func (s RedisStore) setRate(c redis.Conn, key string, rate Rate) ([]int, error) {
            c.Send("MULTI")
            c.Send("SETNX", key, 1)
            c.Send("EXPIRE", key, rate.Period.Seconds())
            return redis.Ints(c.Do("EXEC"))
     }
    

    if the key exist in redis, the function will refresh the expire time of the key, it's design so or bug?

    opened by jinhao 5
  • Should be flexible enough to support advanced use-cases

    Should be flexible enough to support advanced use-cases

    We were considering this library to be used for advanced use-cases such as limiting requests based on Graphql query complexity. I see this works great with RPS use-case but it can also support other use-cases if library consumers are allowed to pass an integer value (a variable instead of hard-coded value 1) to increment method available under drivers (redis/memory) ( Inc method ). This way it would be more flexible for user to pass any value to Redis incrby script as per their needs. I think it would be practical to add another method or api to allow this so to extend it for other use cases as well.

    enhancement question 
    opened by Harry-027 4
  • work behind load balancer

    work behind load balancer

    Hello,

    I will deploy my service behind a load balancer, means all of the request from users will send firstly to the load balancer, then the LB will forward the request to my service. In such architecture, it is said by https://aws.amazon.com/premiumsupport/knowledge-center/elb-find-load-balancer-IP/ that '''You can determine the IP addresses associated with an internal load balancer or an internet-facing load balancer by resolving the DNS name of the load balancer. These are the IP addresses where the clients should send the requests that are destined for the load balancer. However, Classic Load Balancers and Application Load Balancers use the private IP addresses associated with their elastic network interfaces as the source IP address for requests forwarded to your web servers.''' In such architecture, if the source IP of the request is the IP of the load balancer (not the IP of the end user), if ulule apply the request rate limitation, it will in fact limit the total output of the service. Should I do some configuration on ulule limiter or the on the load balancer? or ulule already support such architecture quite well?

    Thanks for your answer,

    James

    question 
    opened by gzhhong 4
  • chore(go.mod): bump github.com/stretchr/testify from 1.7.0 to 1.8.0

    chore(go.mod): bump github.com/stretchr/testify from 1.7.0 to 1.8.0

    Bumps github.com/stretchr/testify from 1.7.0 to 1.8.0.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • chore(go.mod): bump github.com/valyala/fasthttp from 1.34.0 to 1.38.0

    chore(go.mod): bump github.com/valyala/fasthttp from 1.34.0 to 1.38.0

    Bumps github.com/valyala/fasthttp from 1.34.0 to 1.38.0.

    Release notes

    Sourced from github.com/valyala/fasthttp's releases.

    v1.38.0

    • 16d30c4 Support AIX SO_REUSEADDR and SO_REUSEPORT (#1328) (zhangyongding)
    • bc24f9d Consolidate TCPKeepalive in server.Serve (#1320) (#1324) (Y.Horie)
    • 8a32089 Add ConnPoolStrategy field to client (#1317) (Thearas)
    • 35aca7b BodyDecoded() for request and responses (#1308) (Sergey Ponomarev)
    • 66cd502 header.go Referer() optimize (#1313) (Sergey Ponomarev)
    • c9f43ea Response.ContentEncoding(): store as field and avoid using Header.SetCanonical() (#1311) (Sergey Ponomarev)
    • de18824 Optimize server connection close logic (#1310) (Sergey Ponomarev)

    v1.37.0

    • 66bc61e Add an option to allow empty root in the fsHandler (#1299) (RW)
    • 9961079 Fix userdata re-use after Remove (Erik Dubbelboer)

    v1.36.0

    • 7cc6f4c Fix DoTimeout Streaming body bug (Erik Dubbelboer)
    • 9a0b4d0 optimize (#1275) (tyltr)
    • e3d2512 optimize (#1272) (tyltr)
    • b40b5a4 Update tlsClientHandshake (#1263) (Mikhail Faraponov)
    • c7576cc Added Windows support and removed some panics (#1264) (Mauro Leggieri)
    • f0e1be5 add nil check of req.body and resp.body on ReleaseBody (#1266) (zzzzwc)

    v1.35.0

    • 7a5afdd Use %v for errors and %q for strings (#1262) (Erik Dubbelboer)
    • e4a541f support adding/removing clients from LBClient (#1243) (Cam Sweeney)
    • b4152d1 Only set RequestCtx.s once (Erik Dubbelboer)
    • d4c739e State active (#1260) (Erik Dubbelboer)
    • f3bce3a Add Go 1.18 support (#1253) (Aoang)
    • c674263 Fix race conditions in tests (Erik Dubbelboer)
    • 286828e add a test for AppendQuotedArg (#1255) (ZhangYunHao)
    • 2044e1e reduce unnessary type assart (#1254) (tyltr)
    • 3101938 Imporve AppendHTMLEscape fast path (#1249) (ZhangYunHao)
    • d1753f7 bytesconv: add appropriate build tags for s390x (#1250) (Nick Rosbrook)
    • 8f5e51f Add connection pool queuing strategies in HostClient. (#1238) (Y.Horie)
    • f7423e3 Fix AppendHTMLEscape (#1248) (ZhangYunHao)
    • 1a5f2f4 Read response when client closes connection #1232 (#1233) (ArminBTVS)
    Commits
    • 16d30c4 Support AIX SO_REUSEADDR and SO_REUSEPORT (#1328)
    • bc24f9d Consolidate TCPKeepalive in server.Serve (#1320) (#1324)
    • 8a32089 Add ConnPoolStrategy field to client (#1317)
    • 35aca7b BodyDecoded() for request and responses (#1308)
    • 66cd502 header.go Referer() optimize (#1313)
    • c9f43ea Response.ContentEncoding(): store as field and avoid using Header.SetCanonica...
    • de18824 Optimize server connection close logic (#1310)
    • 66bc61e Add an option to allow empty root in the fsHandler (#1299)
    • 9961079 Fix userdata re-use after Remove
    • 7cc6f4c Fix DoTimeout Streaming body bug
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • chore(go.mod): bump github.com/gin-gonic/gin from 1.7.7 to 1.8.1

    chore(go.mod): bump github.com/gin-gonic/gin from 1.7.7 to 1.8.1

    Bumps github.com/gin-gonic/gin from 1.7.7 to 1.8.1.

    Release notes

    Sourced from github.com/gin-gonic/gin's releases.

    v1.8.1

    Changelog

    Features

    • f197a8b feat(context): add ContextWithFallback feature flag (#3166) (#3172)

    v1.8.0

    Changelog

    Break Changes

    • TrustedProxies: Add default IPv6 support and refactor #2967. Please replace RemoteIP() (net.IP, bool) with RemoteIP() net.IP
    • gin.Context with fallback value from gin.Context.Request.Context() #2751

    BUGFIXES

    • Fixed SetOutput() panics on go 1.17 #2861
    • Fix: wrong when wildcard follows named param #2983
    • Fix: missing sameSite when do context.reset() #3123

    ENHANCEMENTS

    • Use Header() instead of deprecated HeaderMap #2694
    • RouterGroup.Handle regular match optimization of http method #2685
    • Add support go-json, another drop-in json replacement #2680
    • Use errors.New to replace fmt.Errorf will much better #2707
    • Use Duration.Truncate for truncating precision #2711
    • Get client IP when using Cloudflare #2723
    • Optimize code adjust #2700
    • Optimize code and reduce code cyclomatic complexity #2737
    • gin.Context with fallback value from gin.Context.Request.Context() #2751
    • Improve sliceValidateError.Error performance #2765
    • Support custom struct tag #2720
    • Improve router group tests #2787
    • Fallback Context.Deadline() Context.Done() Context.Err() to Context.Request.Context() #2769
    • Some codes optimize #2830 #2834 #2838 #2837 #2788 #2848 #2851 #2701
    • Test(route): expose performRequest func #3012
    • Support h2c with prior knowledge #1398
    • Feat attachment filename support utf8 #3071
    • Feat: add StaticFileFS #2749
    • Feat(context): return GIN Context from Value method #2825
    • Feat: automatically SetMode to TestMode when run go test #3139
    • Add TOML bining for gin #3081
    • IPv6 add default trusted proxies #3033

    DOCS

    • Add note about nomsgpack tag to the readme #2703

    ... (truncated)

    Changelog

    Sourced from github.com/gin-gonic/gin's changelog.

    Gin v1.8.1

    ENHANCEMENTS

    • feat(context): add ContextWithFallback feature flag #3172

    Gin v1.8.0

    Break Changes

    • TrustedProxies: Add default IPv6 support and refactor #2967. Please replace RemoteIP() (net.IP, bool) with RemoteIP() net.IP
    • gin.Context with fallback value from gin.Context.Request.Context() #2751

    BUGFIXES

    • Fixed SetOutput() panics on go 1.17 #2861
    • Fix: wrong when wildcard follows named param #2983
    • Fix: missing sameSite when do context.reset() #3123

    ENHANCEMENTS

    • Use Header() instead of deprecated HeaderMap #2694
    • RouterGroup.Handle regular match optimization of http method #2685
    • Add support go-json, another drop-in json replacement #2680
    • Use errors.New to replace fmt.Errorf will much better #2707
    • Use Duration.Truncate for truncating precision #2711
    • Get client IP when using Cloudflare #2723
    • Optimize code adjust #2700
    • Optimize code and reduce code cyclomatic complexity #2737
    • Improve sliceValidateError.Error performance #2765
    • Support custom struct tag #2720
    • Improve router group tests #2787
    • Fallback Context.Deadline() Context.Done() Context.Err() to Context.Request.Context() #2769
    • Some codes optimize #2830 #2834 #2838 #2837 #2788 #2848 #2851 #2701
    • TrustedProxies: Add default IPv6 support and refactor #2967
    • Test(route): expose performRequest func #3012
    • Support h2c with prior knowledge #1398
    • Feat attachment filename support utf8 #3071
    • Feat: add StaticFileFS #2749
    • Feat(context): return GIN Context from Value method #2825
    • Feat: automatically SetMode to TestMode when run go test #3139
    • Add TOML bining for gin #3081
    • IPv6 add default trusted proxies #3033

    DOCS

    • Add note about nomsgpack tag to the readme #2703
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • ERR bad lua script for redis cluster

    ERR bad lua script for redis cluster

    failed to load "incr" lua script: ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array, and KEYS should not be in expression local ret = redis.call("incrby", KEYS[1], ARGV[1])

    opened by xiaozhaofu 1
  • Rate limiting based on custom identity

    Rate limiting based on custom identity

    How can I rate-limit based on custom identity like a variable that loaded from database and not an IP Address

    The rate limit are also difference between each identity

    My framework are Gin, It is possible to do this with this library?

    opened by batara666 1
Releases(v3.10.0)
  • v3.10.0(Mar 17, 2022)

    Changelog

    • Add warnings about using HTTP headers to obtain users IP
    • Add WithClientIPHeader new option
    • Upgrade dependencies
      • Including fasthttp to v1.34.0

    Warning

    If you use limiter behind a reverse proxy, please be extremely careful of your network topology / configuration. If you enable WithTrustForwardHeader option, wrongfully used this could enable spoofable IP. Please read the README and understand the implication of relying on X-Real-IP and/or X-Forwarded-For headers.

    Links:

    • #181
    • #182
    Source code(tar.gz)
    Source code(zip)
  • v3.9.0(Nov 17, 2021)

    Changelog

    • Add new Increment method in store drivers to allow rate limiting based on a variable
    • Upgrade dependencies
    • Change minimal supported version of Go to 1.17

    Links:

    • #172
    Source code(tar.gz)
    Source code(zip)
  • v3.8.0(Dec 7, 2020)

  • v3.7.1(Nov 12, 2020)

  • v3.7.0(Nov 6, 2020)

  • v3.6.0(Nov 3, 2020)

  • v3.5.0(Apr 7, 2020)

    Changelog

    • Fix issue with redis that returns PTTL error code in nanoseconds.
    • Add an option on middleware to exclude keys from limiter.

    Links:

    • #90
    • #91
    • #85
    • #93
    Source code(tar.gz)
    Source code(zip)
  • v3.4.2(Mar 9, 2020)

  • v3.4.1(Feb 12, 2020)

  • v3.4.0(Jan 9, 2020)

  • v3.3.3(Nov 25, 2019)

  • v3.3.2(Oct 7, 2019)

    Changelog

    • Upgrade go modules dependencies.
    • Update golang docker image
    • Update redis docker image
    • Fix Reset() issue: do not return an error on a non-existing key

    Links: #64

    Source code(tar.gz)
    Source code(zip)
  • v3.3.1(Jul 31, 2019)

    Changelog

    • Move examples/ directory to its own repository to reduce the dependency graph with go modules.
    • Update github.com/gin-gonic/gin and github.com/go-redis/redis version.
    • Update scripts/lint.
    • Update scripts/test.
    • Add gopher user in go docker image (using scripts/go-wrapper).

    Links: #62

    Source code(tar.gz)
    Source code(zip)
  • v3.3.0(Jul 19, 2019)

  • v3.2.1(Jun 17, 2019)

  • v3.2.0(May 21, 2019)

  • v3.1.0(Jan 17, 2019)

  • v3.0.0(Jan 9, 2019)

    • Add support for IP mask
    • Add support of go modules
    • Break compatibility with dep

    NOTE: Please ask in issues if you require a dep backports.

    Links: #39

    Source code(tar.gz)
    Source code(zip)
  • v2.2.2(Dec 7, 2018)

  • v2.2.1(Nov 2, 2018)

    Fix the default value used to create a new redis store by using DefaultMaxRetry. Thank @andrewhoff

    Links: https://github.com/ulule/limiter/pull/43

    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Mar 5, 2018)

  • v2.1.0(Nov 10, 2017)

    This release changes the default behaviour on how to retrieve real client IP.

    There was a security issue by trusting X-Forwarded-For and X-Real-Ip, so if your server wasn't running behind a well-configured reverse-proxy, someone could do an IP spoofing on the limiter.

    With this release, you have to explicitly define that you want to use these headers.

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Oct 10, 2017)

  • v1.0.0(Aug 18, 2017)

Owner
Ulule
Ulule
Go http middleware handler for request coalescing

HTTP Coala NOTE: a new and improved implementation is available at https://github.com/go-chi/stampede Just a little bit of performance enhancing middl

go-chi 128 Apr 3, 2022
Idiomatic HTTP Middleware for Golang

Negroni Notice: This is the library formerly known as github.com/codegangsta/negroni -- Github will automatically redirect requests to this repository

null 7.2k Aug 17, 2022
A simple blog framework built with GO. Uses HTML files and a JSON dict to give you more control over your content.

Go-Blog A simple template based blog framework. Instructions Built for GO version: 1 See the Documentation or Getting Started pages in the wiki. Notes

Matt West 44 Jul 15, 2022
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Go Resty 6.5k Aug 9, 2022
Simple web framework for go, still quite beta at this point

WFDR Framework - Beta Release New 18/Feb/2012: Updated for go 1.0, new directory layout to take advantage of the go build tool. Background There's a m

null 23 Feb 11, 2021
Simple Contributors Report For Git

git-contrib Creates simple contributors report for git. Useful for different bra

Erman İmer 2 Aug 8, 2022
Dead simple rate limit middleware for Go.

Limiter Dead simple rate limit middleware for Go. Simple API "Store" approach for backend Redis support (but not tied too) Middlewares: HTTP, FastHTTP

Ulule 1.6k Aug 16, 2022
Docker-hub-rate-limit - Show pulling rate status of Docker-hub

Docker-Hub Pull Rate Status This tool shows current status of docker hub pull ra

Tak 1 Jan 28, 2022
Pacemaker - Rate limit library. Currently implemented rate limits are

PaceMaker Rate limit library. Currently implemented rate limits are Fixed window

Marquitos 2 Apr 2, 2022
Simple middleware to rate-limit HTTP requests.

Tollbooth This is a generic middleware to rate-limit HTTP requests. NOTE 1: This library is considered finished. NOTE 2: Major version changes are bac

Didip Kerabat 2.3k Aug 13, 2022
Simple middleware to rate-limit HTTP requests.

Tollbooth This is a generic middleware to rate-limit HTTP requests. NOTE 1: This library is considered finished. NOTE 2: Major version changes are bac

Didip Kerabat 2.3k Aug 13, 2022
Limit-order-book - Limit order books keep records of orders for a given symbol to be traded

Limit Order Book Limit order books keep records of orders for a given symbol to

Michael Bowler 0 Jan 17, 2022
A Golang blocking leaky-bucket rate limit implementation

Go rate limiter This package provides a Golang implementation of the leaky-bucket rate limit algorithm. This implementation refills the bucket based o

Uber Go 3.2k Aug 8, 2022
Automatically create global & local Rate Limit in Istio, support EnvoyFilter versioning!

istio-ratelimit-operator Istio ratelimit operator provide an easy way to configure Global or Local Ratelimit in Istio mesh. Istio ratelimit operator a

Zufar Dhiyaulhaq 22 Aug 1, 2022
Dhrate - Quickly check Dockerhub rate (limit) as an unauthenticated user

Dockerhub Rate A small Go program that returns the Dockerhub rate of an unauthen

Michael Peter 0 Feb 7, 2022
Ratelimit - This package provides a Golang implementation of the leaky-bucket rate limit algorithm

Go rate limiter This package provides a Golang implementation of the leaky-bucke

gofaquan 1 Jul 26, 2022
A very simple rate limiter in go, made as a learning project to learn go and rate limiting patterns!

rate-limiter-go A very simple rate limiter in go, made as a learning project to learn go and rate limiting patterns! Demo: Running the project: To exe

Jean-Raphaël Poulin Arguin 1 Jun 1, 2022
A concurrent rate limiter library for Golang based on Sliding-Window rate limiter algorithm.

ratelimiter A generic concurrent rate limiter library for Golang based on Sliding-window rate limitng algorithm. The implementation of rate-limiter al

Narasimha Prasanna HN 216 Jul 27, 2022
Redis-rate-limiter - An abstraction over redist rate/v9 package

RATE_LIMIT_POC Notes This POC is based on github.com/go-redis/redis_rate/v9 pack

Deepak Pathak 0 Feb 14, 2022
A dead simple, highly performant, highly customizable sessions middleware for go http servers.

If you're interested in jwt's, see my jwt library! Sessions A dead simple, highly performant, highly customizable sessions service for go http servers

Adam Hanna 66 Jul 25, 2022
Gin-errorhandling - Gin Error Handling Middleware is a middleware for the popular Gin framework

Gin Error Handling Middleware Gin Error Handling Middleware is a middleware for

Joseph Woodward 8 Jul 25, 2022
bf.go - A dead simple brainfuck interpreter Slow and simple

bf.go - A dead simple brainfuck interpreter Slow and simple. Can execute pretty much all tested Brainfuck scripts. Installation If you have Go install

Chris 0 Oct 15, 2021
A simple package for executing work in parallel up to a limit.

concurrencylimiter A simple package for executing work concurrently - up to a limit. The intended usecase looks something like: func concurrentlyDo(ta

Edward Stell 0 Dec 19, 2021
A dead simple configuration manager for Go applications

Store Store is a dead simple configuration manager for Go applications. I didn't like existing configuration management solutions like globalconf, tac

Ian P Badtrousers 261 Aug 5, 2022
Dead simple Go database migration library.

migrator Dead simple Go database migration library. Features Simple code Usage as a library, embeddable and extensible on your behalf Support of any d

David Lobe 127 Jul 31, 2022
A dead simple 2D game library for Go

Ebiten (v2) A dead simple 2D game library for Go Ebiten is an open source game library for the Go programming language. Ebiten's simple API allows you

Hajime Hoshi 6.9k Aug 13, 2022
Dead simple, super fast, zero allocation and modular logger for Golang

Onelog Onelog is a dead simple but very efficient JSON logger. It is one of the fastest JSON logger out there. Also, it is one of the logger with the

Francois Parquet 399 Jun 16, 2022
🧶 Dead simple, lightweight tracing.

?? tracer Dead simple, lightweight tracing. ?? Idea The tracer provides API to trace execution flow. func Do(ctx context.Context) { defer tracer.Fetc

Kamil Samigullin 65 Jul 13, 2022
A dead simple, no frills Go cross compile tool

Gox - Simple Go Cross Compilation Gox is a simple, no-frills tool for Go cross compilation that behaves a lot like standard go build. Gox will paralle

Mitchell Hashimoto 4.3k Aug 11, 2022