Files
sundynix-agentix/sundynix-gateway/internal/middleware/guardrail.go
T
Blizzard e5fa0ae36c feat: Gateway store 桩换真实 GORM/Postgres + go-redis (含自动迁移与优雅降级)
第 2 层网关持久层落地,遵守 sundynix_ 表名前缀 + AutoMigrate 约定。

- store: GORM(NamingStrategy 前缀 sundynix_/单数) → User=sundynix_user, Task=sundynix_task
  启动 AutoMigrate;go-redis/v9 滑动窗口限流(Incr+Expire,按 IP)
- 优雅降级:连不上库则 warn 继续(不 fatal),保证无 Docker 的 make demo 仍跑通
- handler: SubmitTask 持久化任务(best-effort),Billing 真实读库返回 tasks_submitted
- main: OpenPostgres/OpenRedis 读 POSTGRES_DSN/REDIS_ADDR 环境变量
- 验证: 4 模块 build ✓;e2e 3 测试 PASS;live 双路径(真实库持久化 + 坏DSN降级)实测通过

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 11:43:53 +08:00

35 lines
917 B
Go

// Package middleware 提供 Guardrail 与限流等接入层中间件。
package middleware
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/sundynix/sundynix-gateway/internal/store"
)
// Guardrail 实现 Harness 的输入/输出护栏(敏感词、注入、配额校验等)。
func Guardrail() gin.HandlerFunc {
return func(c *gin.Context) {
// TODO: 输入护栏校验
c.Next()
// TODO: 输出护栏校验
}
}
// RateLimit 基于 Redis 的会话级限流(按客户端 IP,每分钟上限)。
// Redis 降级时 Allow 始终放行,不阻断业务。
func RateLimit(cache *store.Redis) gin.HandlerFunc {
const perMinute = 120
return func(c *gin.Context) {
ok, _ := cache.Allow(c.Request.Context(), c.ClientIP(), perMinute, time.Minute)
if !ok {
c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "rate limit exceeded"})
return
}
c.Next()
}
}