Files

60 lines
1.3 KiB
Go
Raw Permalink Normal View History

2025-08-03 00:11:15 +08:00
package middleware
import (
"fmt"
"nl-video-api/utility/response"
"time"
"github.com/gogf/gf/v2/database/gredis"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
// RateLimit 限流中间件
func RateLimit(maxRequests int, window time.Duration) func(r *ghttp.Request) {
return func(r *ghttp.Request) {
var (
ctx = r.Context()
client = g.Redis()
key = fmt.Sprintf("rate_limit:%s", r.GetClientIp())
)
// 获取当前请求次数
count, err := client.Get(ctx, key)
if err != nil {
g.Log().Error(ctx, "Redis获取失败:", err)
r.Middleware.Next()
return
}
// 检查是否超过限制
if count.Int() >= maxRequests {
response.Error(r, response.CodeError, "请求过于频繁,请稍后再试")
return
}
// 增加计数
if count.Int() == 0 {
// 第一次请求,设置过期时间
seconds := int64(window.Seconds())
client.Set(ctx, key, 1, gredis.SetOption{
TTLOption: gredis.TTLOption{EX: &seconds},
})
} else {
// 增加计数
client.Incr(ctx, key)
}
r.Middleware.Next()
}
}
// APIRateLimit API接口限流每分钟60次
func APIRateLimit(r *ghttp.Request) {
RateLimit(60, time.Minute)(r)
}
// LoginRateLimit 登录接口限流每分钟5次
func LoginRateLimit(r *ghttp.Request) {
RateLimit(5, time.Minute)(r)
}