Files
GovAI/server/internal/middleware/ratelimit.go
T
selfrelease 65dc805eb5 feat: 系统优化 - ESLint、Tailwind、前端健壮性、后端工程化、运维可观测性
- 前端: ESLint+Prettier配置、Tailwind v4配置、ErrorBoundary、全局AuthLoader优化、ReactQuery分层
- 后端: MinIO凭证移除、Docker统一为govai品牌、zerolog日志封装、错误码枚举、文件上传校验、单元测试(13项全通过)
- 运维: 健康检查增强(PG/Redis ping)、Prometheus指标(/metrics端点)、多租户tenant包、RateLimit nil防御
- 移动: citation_prompt.txt → internal/assets/
2026-06-23 14:48:31 +08:00

45 lines
979 B
Go

package middleware
import (
"context"
"fmt"
"net/http"
"time"
"github.com/enterprise-ai-platform/server/internal/response"
"github.com/redis/go-redis/v9"
)
// RateLimit creates a per-user rate limiter using Redis sliding window.
func RateLimit(rdb *redis.Client, maxRequests int, window time.Duration) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if rdb == nil {
next.ServeHTTP(w, r)
return
}
userID := GetUserID(r.Context())
key := fmt.Sprintf("rl:%s:%s", userID.String(), r.URL.Path)
ctx := context.Background()
count, err := rdb.Incr(ctx, key).Result()
if err != nil {
next.ServeHTTP(w, r)
return
}
if count == 1 {
rdb.Expire(ctx, key, window)
}
if count > int64(maxRequests) {
response.TooManyRequests(w, "请求过于频繁,请稍后再试")
return
}
next.ServeHTTP(w, r)
})
}
}