12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- package middleware
- import (
- "fmt"
- "time"
- "gitee.com/xuyiping_admin/pkg/apierr"
- "gitee.com/xuyiping_admin/pkg/xerr"
- "github.com/gin-gonic/gin"
- limit "github.com/yangxikun/gin-limit-by-key"
- "golang.org/x/time/rate"
- )
- // RateLimit limit rate by client ip
- // limit 10 qps/client_ip and permit bursts of at most 10 tokens, and the limiter live time duration is 3 minutes
- // handle exceed rate limit request
- func RateLimit(opts ...*RateLimitOption) gin.HandlerFunc {
- var opt *RateLimitOption
- if len(opts) == 0 {
- opt = defaultRateLimitOption
- } else {
- opt = opts[0]
- }
- return limit.NewRateLimiter(func(c *gin.Context) string {
- return fmt.Sprintf("%s-%s", c.ClientIP(), authorization(c))
- }, func(c *gin.Context) (*rate.Limiter, time.Duration) {
- return rate.NewLimiter(rate.Every(opt.Interval), opt.Tokens), opt.LiveTime
- }, func(c *gin.Context) {
- apierr.AbortBadRequest(c, 429, xerr.Customf("request too many %s", c.ClientIP()))
- })
- }
- type RateLimitOption struct {
- Interval time.Duration
- Tokens int
- LiveTime time.Duration
- }
- var defaultRateLimitOption = &RateLimitOption{
- Interval: 100 * time.Millisecond,
- Tokens: 10,
- LiveTime: 3 * time.Minute,
- }
- var testRateLimitOption = &RateLimitOption{
- Interval: 10 * time.Millisecond,
- Tokens: 1000,
- LiveTime: 1 * time.Minute,
- }
- func RateLimitOptionLow() *RateLimitOption {
- return &RateLimitOption{
- Interval: 1 * time.Second,
- Tokens: 10,
- LiveTime: 3 * time.Minute,
- }
- }
|