cerrado @ e1664fcbc4685906d3dabc66bf947a17bce7efc0

 1package ext
 2
 3import (
 4	"log/slog"
 5	"net/http"
 6	"time"
 7)
 8
 9type statusWraper struct {
10	statusCode  int
11	size        int
12	innerWriter http.ResponseWriter
13}
14
15func (s *statusWraper) Header() http.Header {
16	return s.innerWriter.Header()
17}
18
19func (s *statusWraper) Write(b []byte) (int, error) {
20	s.size += len(b)
21	return s.innerWriter.Write(b)
22}
23
24func (s *statusWraper) WriteHeader(statusCode int) {
25	s.statusCode = statusCode
26	s.innerWriter.WriteHeader(statusCode)
27}
28
29func (s *statusWraper) StatusCode() int {
30	if s.statusCode == 0 {
31		return 200
32	}
33	return s.statusCode
34}
35
36func wrap(w http.ResponseWriter) *statusWraper {
37	return &statusWraper{
38		innerWriter: w,
39	}
40}
41
42func Log(next http.HandlerFunc) http.HandlerFunc {
43	return func(w http.ResponseWriter, r *http.Request) {
44		t := time.Now()
45		s := wrap(w)
46		next(s, r)
47		encoding := s.Header().Get("Content-Encoding")
48		slog.Info(
49			"HTTP request",
50			"method", r.Method,
51			"code", s.StatusCode(),
52			"path", r.URL,
53			"encoding", encoding,
54			"elapsed", time.Since(t),
55			"body-size", s.size,
56		)
57	}
58}