Files

98 lines
2.1 KiB
Go
Raw Permalink Normal View History

2025-07-23 17:30:33 +08:00
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")
})
}