- 更新 changelog.md: v0.2.0 记录 M2-M8 全部完成,路线图更新 - 新增 5 篇指南: RBAC、组织管理、审计日志、通知模块、质量横切 - 新增 5 篇 API 文档: RBAC(11)、Org(5)、Audit(1)、Settings(7)、Notification(7) - 更新 api/overview.md: 完整 37 端点列表 - 更新 config.ts: 侧边栏分组 + 11 页 SEO 元数据
3.6 KiB
3.6 KiB
| title |
|---|
| 质量横切 | 安全基线、限流、日志与优雅停机 - MengStack官方文档 |
质量横切
M8 为框架添加了生产级质量基线,覆盖安全、限流、日志、容错和测试基础设施。
中间件链
所有请求经过以下中间件链(按顺序):
RequestID → RequestLogger → SecurityHeaders → CORS → RateLimit → BodyLimit → Recovery
IP 限流
基于内存的 IP 限流中间件,自动清理过期记录:
// 每个 IP 每分钟最多 100 次请求
r.Use(middleware.RateLimit(100, time.Minute))
| 特性 | 说明 |
|---|---|
| 限流维度 | 客户端 IP |
| 存储方式 | 内存 map + sync.Mutex |
| 自动清理 | 后台 goroutine 每分钟清理过期记录 |
| 超限响应 | HTTP 429 + RATE_LIMITED 错误码 |
::: warning 内存限流适合单机部署。多实例部署建议替换为 Redis 限流。 :::
安全响应头
自动为所有响应添加安全头:
| Header | 值 | 作用 |
|---|---|---|
X-Content-Type-Options |
nosniff |
防止 MIME 类型嗅探 |
X-Frame-Options |
DENY |
防止点击劫持 |
X-XSS-Protection |
1; mode=block |
浏览器 XSS 过滤 |
Referrer-Policy |
strict-origin-when-cross-origin |
控制 Referer 泄露 |
Content-Security-Policy |
default-src 'self' |
限制资源加载来源 |
请求体限制
限制请求体最大为 10MB,防止大文件攻击:
r.Use(middleware.BodyLimit(10 << 20)) // 10 MB
- 先检查
Content-Lengthheader,超限直接返回 413 - 再通过
http.MaxBytesReader限制实际读取大小
结构化请求日志
使用 Zap 替代 fmt,输出结构化 JSON 日志:
{
"level": "info",
"msg": "request",
"status": 200,
"method": "GET",
"path": "/api/v1/profile",
"query": "",
"ip": "192.168.1.100",
"user-agent": "Mozilla/5.0",
"latency_ms": 12,
"trace_id": "req-abc-123"
}
日志级别按状态码自动选择:
| 状态码范围 | 日志级别 |
|---|---|
| < 400 | INFO |
| 400-499 | WARN |
| >= 500 | ERROR |
自定义 Recovery
替代 gin.Recovery(),panic 信息通过 Zap 记录而非 stdout:
r.Use(middleware.Recovery(log))
记录的字段:panic 内容、stack trace、请求方法、路径、trace_id。
优雅停机
应用收到终止信号后,等待最多 10 秒处理完进行中的请求:
// app.go
OnStop: func(ctx context.Context) error {
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return srv.Shutdown(shutdownCtx)
}
测试基础设施
testutil 包
import "mengstack/internal/kernel/testutil"
func TestSomething(t *testing.T) {
log := testutil.TestLogger(t) // 测试专用 Zap logger
cfg := testutil.TestConfig() // 最小化测试配置
}
中间件测试
内置 11 个单元测试覆盖所有中间件:
go test ./internal/app/middleware/ -v
| 测试 | 覆盖场景 |
|---|---|
| TestRequestID_GeneratesNew | 无 trace_id 时自动生成 |
| TestRequestID_PreservesExisting | 已有 trace_id 时保留 |
| TestSecurityHeaders | 5 个安全头全部设置 |
| TestRateLimit_AllowsWithinLimit | 限额内请求正常通过 |
| TestRateLimit_BlocksOverLimit | 超限额返回 429 |
| TestRequestLogger_DoesNotPanic | 日志中间件不 panic |
| TestRecovery_HandlesPanic | 捕获 panic 并记录 |
| TestBodyLimit_RejectsLargeBody | 超大 body 返回 413 |
| TestBodyLimit_AllowsSmallBody | 正常 body 通过 |
数据库时区
PostgreSQL DSN 默认携带 TimeZone=Asia/Shanghai,确保时间字段按中国时区存储和返回。