补齐 HTTP 层:实现用户模块、路由与中间件接线、COS 上传及优雅启动

- 新增用户与上传错误码文件及 Recovery 中间件
- 修复 router.go 导入与中间件链,注册用户路由并补 handler 错误码导入
- 补充用户状态常量与 UserGetByWechatOpenID 查询,修订刷新令牌 dto
- 移除 upload 包 OTel 调用,新增 FileUploadCos 上传封装
- 实现 UserService 微信登录/刷新令牌/我的信息/改资料/上传头像
- 裁剪 main.go 配置段并移除 OTel 桥接,补启动与优雅退出
- 新增 configs 示例配置、global 配置结构及 go.mod 依赖
This commit is contained in:
2026-09-27 15:02:01 +08:00
parent 8f08d94a56
commit ff9add8655
33 changed files with 2473 additions and 0 deletions
+77
View File
@@ -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...)
}
}
}