chore: initial commit of ai site platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-07-31 10:31:17 +08:00
commit 4ca82fb58a
203 changed files with 45745 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
package ratelimit
import (
"net"
"net/http"
"strings"
"sync"
"time"
)
type Limiter struct {
mu sync.Mutex
visitors map[string]*visitor
rate int // 0 = disabled
window time.Duration
}
type visitor struct {
count int
reset time.Time
}
// New creates a per-IP limiter. ratePerMinute <= 0 disables limiting.
func New(ratePerMinute int) *Limiter {
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) {
if l.rate <= 0 {
next(w, r)
return
}
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil || ip == "" {
ip = r.RemoteAddr
}
// 本机开发Vite 代理与所有本机请求共用 127.0.0.1,不做限流
if isLoopback(ip) {
next(w, r)
return
}
if !l.allow(ip) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusTooManyRequests)
_, _ = w.Write([]byte(`{"code":429,"message":"gateway rate limit exceeded"}`))
return
}
next(w, r)
}
}
func isLoopback(ip string) bool {
ip = strings.Trim(ip, "[]")
if ip == "127.0.0.1" || ip == "::1" || ip == "localhost" {
return true
}
parsed := net.ParseIP(ip)
return parsed != nil && parsed.IsLoopback()
}
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
}