2026-03-31 13:40:00 +08:00
|
|
|
|
package middleware
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-04-13 09:49:58 +08:00
|
|
|
|
"fmt"
|
2026-03-31 13:40:00 +08:00
|
|
|
|
"net/http"
|
|
|
|
|
|
"runtime/debug"
|
2026-04-08 07:44:58 +08:00
|
|
|
|
|
|
|
|
|
|
"lijiaoqiao/supply-api/internal/pkg/logging"
|
2026-03-31 13:40:00 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Recovery 中间件 - 恢复 panic
|
|
|
|
|
|
func Recovery(next http.Handler) http.Handler {
|
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
if err := recover(); err != nil {
|
2026-04-13 09:49:58 +08:00
|
|
|
|
// 使用结构化日志记录 panic
|
|
|
|
|
|
logger := logging.NewLogger("supply-api", logging.LogLevelError)
|
|
|
|
|
|
logger.Error("panic recovered", map[string]interface{}{
|
|
|
|
|
|
"error": fmt.Sprintf("%v", err),
|
|
|
|
|
|
"stack": string(debug.Stack()),
|
|
|
|
|
|
"path": r.URL.Path,
|
|
|
|
|
|
"method": r.Method,
|
|
|
|
|
|
})
|
2026-03-31 13:40:00 +08:00
|
|
|
|
http.Error(w, "internal server error", http.StatusInternalServerError)
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-08 07:44:58 +08:00
|
|
|
|
// Logging 中间件 - 请求日志(使用结构化JSON日志)
|
|
|
|
|
|
// P1-010修复: 使用结构化日志替代标准log
|
|
|
|
|
|
func Logging(next http.Handler, logger logging.Logger) http.Handler {
|
2026-03-31 13:40:00 +08:00
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2026-04-08 07:44:58 +08:00
|
|
|
|
// 从context获取追踪信息
|
|
|
|
|
|
fields := make(map[string]interface{})
|
|
|
|
|
|
fields["method"] = r.Method
|
|
|
|
|
|
fields["path"] = r.URL.Path
|
|
|
|
|
|
fields["query"] = r.URL.RawQuery
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试获取request_id
|
|
|
|
|
|
if requestID := r.Header.Get("X-Request-Id"); requestID != "" {
|
|
|
|
|
|
fields["request_id"] = requestID
|
|
|
|
|
|
} else if requestID := r.Header.Get("X-Request-ID"); requestID != "" {
|
|
|
|
|
|
fields["request_id"] = requestID
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试获取trace_id
|
|
|
|
|
|
if tc, ok := GetTraceContext(r.Context()); ok {
|
|
|
|
|
|
fields["trace_id"] = tc.TraceID
|
|
|
|
|
|
fields["span_id"] = tc.SpanID
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logger.Info("HTTP request", fields)
|
2026-03-31 13:40:00 +08:00
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RequestID 中间件 - 请求追踪
|
|
|
|
|
|
func RequestID(next http.Handler) http.Handler {
|
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
requestID := r.Header.Get("X-Request-Id")
|
|
|
|
|
|
if requestID == "" {
|
|
|
|
|
|
requestID = r.Header.Get("X-Request-ID")
|
|
|
|
|
|
}
|
|
|
|
|
|
if requestID != "" {
|
|
|
|
|
|
w.Header().Set("X-Request-Id", requestID)
|
|
|
|
|
|
}
|
|
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|