补齐 HTTP 层:实现用户模块、路由与中间件接线、COS 上传及优雅启动
- 新增用户与上传错误码文件及 Recovery 中间件 - 修复 router.go 导入与中间件链,注册用户路由并补 handler 错误码导入 - 补充用户状态常量与 UserGetByWechatOpenID 查询,修订刷新令牌 dto - 移除 upload 包 OTel 调用,新增 FileUploadCos 上传封装 - 实现 UserService 微信登录/刷新令牌/我的信息/改资料/上传头像 - 裁剪 main.go 配置段并移除 OTel 桥接,补启动与优雅退出 - 新增 configs 示例配置、global 配置结构及 go.mod 依赖
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// sanitizeQuery 对 query 中的敏感参数值脱敏,避免日志泄露 token/code/密钥等。
|
||||
func sanitizeQuery(query string) string {
|
||||
if query == "" {
|
||||
return ""
|
||||
}
|
||||
values, err := url.ParseQuery(query)
|
||||
if err != nil {
|
||||
return "***"
|
||||
}
|
||||
sensitive := map[string]bool{
|
||||
"token": true, "code": true, "secret": true, "password": true,
|
||||
"access_token": true, "refresh_token": true, "key": true,
|
||||
}
|
||||
for k := range values {
|
||||
if sensitive[strings.ToLower(k)] {
|
||||
values.Set(k, "***")
|
||||
}
|
||||
}
|
||||
return values.Encode()
|
||||
}
|
||||
|
||||
// maxUserAgentLen user_agent 日志字段最大长度:超出截断,避免异常长 UA 撑大日志体积。
|
||||
const maxUserAgentLen = 256
|
||||
|
||||
// truncateUserAgent 截断超长 User-Agent(仅用于日志展示)。
|
||||
func truncateUserAgent(ua string) string {
|
||||
if len(ua) <= maxUserAgentLen {
|
||||
return ua
|
||||
}
|
||||
return ua[:maxUserAgentLen] + "...(truncated)"
|
||||
}
|
||||
|
||||
func GinSlogMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
|
||||
start := time.Now()
|
||||
path := c.Request.URL.Path
|
||||
query := sanitizeQuery(c.Request.URL.RawQuery)
|
||||
|
||||
// 处理请求
|
||||
c.Next()
|
||||
|
||||
// 请求结束后按状态码分级打日志:5xx=Error、4xx(除 401)=Warn、其余=Info。
|
||||
ctx := c.Request.Context()
|
||||
status := c.Writer.Status()
|
||||
attrs := []any{
|
||||
"request_id", GetRequestID(ctx),
|
||||
"method", c.Request.Method,
|
||||
"path", path,
|
||||
"query", query,
|
||||
"status", status,
|
||||
"ip", c.ClientIP(),
|
||||
"latency", time.Since(start).String(),
|
||||
"user_agent", truncateUserAgent(c.Request.UserAgent()),
|
||||
}
|
||||
switch {
|
||||
case status >= http.StatusInternalServerError:
|
||||
slog.ErrorContext(ctx, "GIN_REQUEST", attrs...)
|
||||
case status >= http.StatusBadRequest && status != http.StatusUnauthorized:
|
||||
slog.WarnContext(ctx, "GIN_REQUEST", attrs...)
|
||||
default:
|
||||
slog.InfoContext(ctx, "GIN_REQUEST", attrs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user