Files
jiang13-bbs/backend/service/ratelimit.go
freefire a83276060f feat: 站点单页、时间线导入与行级 BBCode 短代码
首页右栏接入单页入口与公告置顶/全部页;Markdown 编辑器支持可视化时间线与 Git 导入;隐藏块改为 [hide]/[timeline] 命名闭合,并修复单页/公告 GORM 更新只改 updated_at 的问题。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 19:52:06 +08:00

90 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"sync"
"time"
)
// RateLimiter 内存速率限制器
type RateLimiter struct {
mu sync.Mutex
records map[string][]time.Time
limits map[string]int // key -> 每分钟最大请求数
cooldown map[string]time.Duration
}
func NewRateLimiter() *RateLimiter {
return &RateLimiter{
records: make(map[string][]time.Time),
limits: make(map[string]int),
cooldown: make(map[string]time.Duration),
}
}
// SetLimit 设置某类请求的每分钟限制
func (r *RateLimiter) SetLimit(key string, perMinute int) {
r.mu.Lock()
defer r.mu.Unlock()
r.limits[key] = perMinute
}
// Allow 检查是否允许请求
func (r *RateLimiter) Allow(key string) bool {
r.mu.Lock()
defer r.mu.Unlock()
limit, ok := r.limits[key]
if !ok {
return true
}
now := time.Now()
windowStart := now.Add(-1 * time.Minute)
// 清理过期记录
records := r.records[key]
valid := records[:0]
for _, t := range records {
if t.After(windowStart) {
valid = append(valid, t)
}
}
if len(valid) >= limit {
r.records[key] = valid
return false
}
valid = append(valid, now)
r.records[key] = valid
return true
}
// 速率限制类型常量
const (
RateLogin = "login"
RateRegister = "register"
RatePost = "post"
RateComment = "comment"
RateChat = "chat" // 群聊发消息
RateUpload = "upload" // 帖子插图等上传
RateInteract = "interact" // 投票/抽奖/解锁等互动
RateHidePassword = "hide_password" // 密码隐藏块尝试
RateTimelineGit = "timeline_git" // Git 提交导入 10/分钟
)
// DefaultRateLimiter 创建默认速率限制器
func DefaultRateLimiter() *RateLimiter {
rl := NewRateLimiter()
rl.SetLimit(RateLogin, 20) // 登录 20/分钟
rl.SetLimit(RateRegister, 10) // 注册 10/分钟
rl.SetLimit(RatePost, 10) // 发帖 10/分钟
rl.SetLimit(RateComment, 30) // 评论 30/分钟
rl.SetLimit(RateChat, 30) // 群聊消息 30/分钟
rl.SetLimit(RateUpload, 20) // 图片上传 20/分钟
rl.SetLimit(RateInteract, 40) // 互动 40/分钟
rl.SetLimit(RateHidePassword, 20) // 密码尝试 20/分钟(按 IP)
rl.SetLimit(RateTimelineGit, 10) // 时间线 Git 导入 10/分钟
return rl
}