-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add DefaultRedis wrapper - fix middleware nil pointer - upd linter - upd pipeline - upd docs
- Loading branch information
1 parent
47694f6
commit 7d77436
Showing
5 changed files
with
149 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,130 @@ | ||
# go-ratelimiter | ||
A super easy rate limiting package for Go | ||
|
||
A super easy rate limiting package for Go. Package defines Store storage interface, for which you can use your own | ||
implementations | ||
|
||
# Install | ||
|
||
```shell | ||
go get github.com/robotomize/go-ratelimiter | ||
``` | ||
|
||
# Usage | ||
|
||
Example of using redis datastore | ||
|
||
```go | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/robotomize/go-ratelimiter" | ||
) | ||
|
||
func main() { | ||
// set a limit of 10 request per 1 seconds per api key | ||
redisStore, err := ratelimiter.DefaultRedisStore(context.Background(), ":6379", 1*time.Second, 10) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// Retrieve data by the api key in the datastore | ||
limit, remaining, resetTime, ok, err := redisStore.Take(context.Background(), "apikey-1") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
if !ok { | ||
fmt.Println("limit exceeded") | ||
} | ||
|
||
// Print the constraints from the datastore | ||
fmt.Printf( | ||
"resource: maximum %d, remaining %d, reset time %s", | ||
limit, remaining, time.Unix(0, int64(resetTime)).UTC().Format(time.RFC1123), | ||
) | ||
} | ||
|
||
``` | ||
|
||
To limit access at the http level, you can use middleware, which can block the request by providing the http code 429 | ||
Too Many Requests | ||
|
||
Example of using http middleware with redis datastore | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"log" | ||
"net/http" | ||
"os" | ||
"time" | ||
|
||
"github.com/robotomize/go-ratelimiter" | ||
) | ||
|
||
func main() { | ||
// set a limit of 5 request per 1 seconds per api key | ||
redisStore, err := ratelimiter.DefaultRedisStore(context.Background(), ":6379", 1*time.Second, 5) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
mx := http.NewServeMux() | ||
// Let's create a test handler | ||
healthHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(http.StatusOK) | ||
w.Write([]byte(`{"status": "ok"}`)) | ||
}) | ||
|
||
mx.Handle( | ||
"/health", ratelimiter.LimiterMiddleware( | ||
redisStore, func(r *http.Request) (string, error) { | ||
// Example key func | ||
ctx := r.Context() | ||
// Get key value out of context | ||
ctxValue := ctx.Value("apikey") | ||
if key, ok := ctxValue.(string); ok { | ||
return key, nil | ||
} | ||
|
||
return "", errors.New("get api key from ctx") | ||
}, ratelimiter.WithSkipper(func() bool { | ||
// set a skipper, skip ratelimiter if DEBUG == 1 | ||
return os.Getenv("DEBUG") == "1" | ||
}, ), | ||
)(healthHandler), | ||
) | ||
|
||
// start listener | ||
if err = http.ListenAndServe(":8888", mx); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
``` | ||
|
||
# TODO | ||
|
||
* ~add http middleware~ | ||
* ~add simple redis datastore~ | ||
* extend Store methods | ||
* improve redis datastore | ||
* try using tarantool datastore | ||
* try using aerospike datastore | ||
|
||
## Contributing | ||
|
||
|
||
## License | ||
|
||
go-ratelimiter is under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters