Files
junhong_cmp_fiber/pkg/logger/middleware.go
huang 6f1350b527
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m31s
修复日志中间件的 UserID 类型转换 panic 问题
问题描述:
- 认证中间件存储的 UserID 是 uint 类型
- 日志中间件和错误上下文错误地将其断言为 string 类型
- 导致所有认证请求在记录访问日志时发生 panic

修复内容:
1. pkg/logger/middleware.go
   - 修改 UserID 变量类型从 string 为 uint
   - 使用安全的类型断言 (uid.(uint))
   - 使用 zap.Uint 记录日志

2. pkg/errors/context.go
   - 修改 UserID 类型断言从 string 为 uint
   - 使用 strconv.FormatUint 转换为 string 用于错误上下文

影响范围:
- 修复所有需要认证的接口的 panic 错误
- 包括 /api/admin/shops, /api/admin/me, /api/admin/permissions 等
2026-01-21 12:17:19 +08:00

86 lines
2.1 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 logger
import (
"time"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
const (
// MaxBodyLogSize 限制记录的请求/响应 body 大小为 50KB
MaxBodyLogSize = 50 * 1024
)
// truncateBody 截断 body 到指定大小
func truncateBody(body []byte, maxSize int) string {
if len(body) == 0 {
return ""
}
if len(body) <= maxSize {
return string(body)
}
// 超过限制,截断并添加提示
return string(body[:maxSize]) + "... (truncated)"
}
// Middleware 创建 Fiber 日志中间件
// 记录所有 HTTP 请求到访问日志(包括请求和响应 body
func Middleware() fiber.Handler {
return func(c *fiber.Ctx) error {
// 记录请求开始时间
startTime := time.Now()
c.Locals(constants.ContextKeyStartTime, startTime)
// 获取请求 body在 c.Next() 之前读取)
requestBody := truncateBody(c.Body(), MaxBodyLogSize)
// 获取 query 参数
queryParams := string(c.Request().URI().QueryString())
// 处理请求
err := c.Next()
// 计算请求持续时间
duration := time.Since(startTime)
// 获取请求 ID由 requestid 中间件设置)
requestID := ""
if rid := c.Locals(constants.ContextKeyRequestID); rid != nil {
requestID = rid.(string)
}
// 获取用户 ID由 auth 中间件设置)
var userID uint
if uid := c.Locals(constants.ContextKeyUserID); uid != nil {
if id, ok := uid.(uint); ok {
userID = id
}
}
// 获取响应 body
responseBody := truncateBody(c.Response().Body(), MaxBodyLogSize)
// 记录访问日志
accessLogger := GetAccessLogger()
accessLogger.Info("",
zap.String("method", c.Method()),
zap.String("path", c.Path()),
zap.String("query", queryParams),
zap.Int("status", c.Response().StatusCode()),
zap.Float64("duration_ms", float64(duration.Microseconds())/1000.0),
zap.String("request_id", requestID),
zap.String("ip", c.IP()),
zap.String("user_agent", c.Get("User-Agent")),
zap.Uint("user_id", userID),
zap.String("request_body", requestBody),
zap.String("response_body", responseBody),
)
return err
}
}