package middleware import ( "net/http" "time" "git.toowon.com/jimmy/go-common/logger" ) // responseWriter 包装 ResponseWriter 以捕获状态码 type responseWriter struct { http.ResponseWriter statusCode int } func (rw *responseWriter) WriteHeader(statusCode int) { rw.statusCode = statusCode rw.ResponseWriter.WriteHeader(statusCode) } // LoggingConfig 日志中间件配置 type LoggingConfig struct { Logger *logger.Logger SkipPaths []string } // Logging HTTP 访问日志(固定 Info 级别) func Logging(config *LoggingConfig) func(http.Handler) http.Handler { if config == nil { config = &LoggingConfig{} } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if shouldSkipPath(r.URL.Path, config.SkipPaths) { next.ServeHTTP(w, r) return } start := time.Now() rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK} next.ServeHTTP(rw, r) fields := map[string]any{ "method": r.Method, "path": r.URL.Path, "duration": time.Since(start).Milliseconds(), } log := logger.FromContext(r.Context()) if config.Logger != nil { log = logger.FromContextWithLogger(r.Context(), config.Logger) } log.Info("HTTP Request", fields) }) } } func shouldSkipPath(path string, skipPaths []string) bool { for _, skip := range skipPaths { if path == skip { return true } } return false }