chore: initial commit of ai site platform
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
84
platform/internal/ratelimit/limiter.go
Normal file
84
platform/internal/ratelimit/limiter.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"aijianzhan/platform/internal/authx"
|
||||
)
|
||||
|
||||
type Limiter struct {
|
||||
mu sync.Mutex
|
||||
visitors map[string]*visitor
|
||||
rate int
|
||||
window time.Duration
|
||||
}
|
||||
|
||||
type visitor struct {
|
||||
count int
|
||||
reset time.Time
|
||||
}
|
||||
|
||||
func New(ratePerMinute int) *Limiter {
|
||||
if ratePerMinute <= 0 {
|
||||
ratePerMinute = 120
|
||||
}
|
||||
return &Limiter{
|
||||
visitors: map[string]*visitor{},
|
||||
rate: ratePerMinute,
|
||||
window: time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Limiter) Middleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
key := r.RemoteAddr
|
||||
if tid := authx.TenantID(r.Context()); tid > 0 {
|
||||
key = "t:" + itoa(tid)
|
||||
}
|
||||
if !l.allow(key) {
|
||||
authx.WriteError(w, http.StatusTooManyRequests, "rate limit exceeded")
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Limiter) allow(key string) bool {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
now := time.Now()
|
||||
v, ok := l.visitors[key]
|
||||
if !ok || now.After(v.reset) {
|
||||
l.visitors[key] = &visitor{count: 1, reset: now.Add(l.window)}
|
||||
return true
|
||||
}
|
||||
if v.count >= l.rate {
|
||||
return false
|
||||
}
|
||||
v.count++
|
||||
return true
|
||||
}
|
||||
|
||||
func itoa(n int64) string {
|
||||
if n == 0 {
|
||||
return "0"
|
||||
}
|
||||
neg := n < 0
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
var b [20]byte
|
||||
i := len(b)
|
||||
for n > 0 {
|
||||
i--
|
||||
b[i] = byte('0' + n%10)
|
||||
n /= 10
|
||||
}
|
||||
if neg {
|
||||
i--
|
||||
b[i] = '-'
|
||||
}
|
||||
return string(b[i:])
|
||||
}
|
||||
Reference in New Issue
Block a user