package middleware import ( "bytes" "fmt" "io" "net/http" "time" "github.com/sirupsen/logrus" "ca-mini/internal/config" "ca-mini/internal/logger" ) type RequestInfo struct { Method string `json:"method"` Path string `json:"path"` Header http.Header `json:"header"` Body string `json:"body"` } type ResponseInfo struct { Code int `json:"code"` Header http.Header `json:"header"` Body string `json:"body"` } // responseWriter 包装 http.ResponseWriter 以捕获状态码和响应体 type responseWriter struct { http.ResponseWriter statusCode int body *bytes.Buffer } // WriteHeader 捕获状态码 func (rw *responseWriter) WriteHeader(code int) { rw.statusCode = code rw.ResponseWriter.WriteHeader(code) } // Write 捕获响应体 func (rw *responseWriter) Write(b []byte) (int, error) { rw.body.Write(b) return rw.ResponseWriter.Write(b) } // LoggerMiddleware 日志中间件 func LoggerMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cfg, err := config.Load() if err != nil || cfg.Logging.Level == "debug" { next.ServeHTTP(w, r) return } // 开始计时 start := time.Now() // 读取请求体并重置 r.Body var requestBody bytes.Buffer _, err = io.Copy(&requestBody, r.Body) if err != nil { logger.Error("Failed to read request body: %v", err) } r.Body = io.NopCloser(&requestBody) // 创建一个响应包装器来捕获响应状态码和响应体 lrw := &responseWriter{ ResponseWriter: w, statusCode: http.StatusOK, body: &bytes.Buffer{}, } // 处理请求 next.ServeHTTP(lrw, r) // 统计请求处理时间 duration := time.Since(start).Milliseconds() // 记录日志 logger.Logger.WithFields(logrus.Fields{ "request": RequestInfo{ Method: r.Method, Path: r.URL.Path, Header: r.Header, Body: requestBody.String(), }, "response": ResponseInfo{ Code: lrw.statusCode, Header: lrw.Header(), Body: lrw.body.String(), }, "duration": fmt.Sprintf("%dms", duration), }).Debug("Request processed") }) }