1package server
2
3import (
4 "log/slog"
5 "net/http"
6 "time"
7)
8
9func (s *Server) loggingHandler(next http.Handler) http.Handler {
10 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
11 if s.logger == nil {
12 next.ServeHTTP(w, r)
13 return
14 }
15
16 start := time.Now()
17 lrw := &loggingResponseWriter{ResponseWriter: w, statusCode: http.StatusOK}
18 s.logger.Debug("HTTP request",
19 slog.String("method", r.Method),
20 slog.String("path", r.URL.Path),
21 slog.String("remote_addr", r.RemoteAddr),
22 slog.String("user_agent", r.UserAgent()),
23 )
24
25 next.ServeHTTP(lrw, r)
26 duration := time.Since(start)
27
28 s.logger.Debug("HTTP response",
29 slog.String("method", r.Method),
30 slog.String("path", r.URL.Path),
31 slog.Int("status", lrw.statusCode),
32 slog.Duration("duration", duration),
33 slog.String("remote_addr", r.RemoteAddr),
34 slog.String("user_agent", r.UserAgent()),
35 )
36 })
37}
38
39type loggingResponseWriter struct {
40 http.ResponseWriter
41 statusCode int
42}
43
44func (lrw *loggingResponseWriter) WriteHeader(code int) {
45 lrw.statusCode = code
46 lrw.ResponseWriter.WriteHeader(code)
47}
48
49func (lrw *loggingResponseWriter) Unwrap() http.ResponseWriter {
50 return lrw.ResponseWriter
51}