• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cshum / imagor / 8184564833

07 Mar 2024 07:39AM UTC coverage: 89.369% (-0.02%) from 89.384%
8184564833

Pull #413

github

cshum
refactor: exclude healthcheck from access logs
Pull Request #413: refactor: exclude healthcheck from access logs

11 of 14 new or added lines in 2 files covered. (78.57%)

7 existing lines in 1 file now uncovered.

5691 of 6368 relevant lines covered (89.37%)

1.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.02
/server/handler.go
1
package server
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "log"
7
        "net/http"
8
        "strconv"
9
        "strings"
10
        "time"
11

12
        "go.uber.org/zap"
13
)
14

15
type errResp struct {
16
        Message string `json:"message,omitempty"`
17
        Code    int    `json:"status,omitempty"`
18
}
19

UNCOV
20
func handleOk(w http.ResponseWriter, r *http.Request) {
×
UNCOV
21
        w.WriteHeader(http.StatusOK)
×
UNCOV
22
        return
×
UNCOV
23
}
×
24

25
func (s *Server) panicHandler(next http.Handler) http.Handler {
1✔
26
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2✔
27
                defer func() {
2✔
28
                        if rvr := recover(); rvr != nil {
2✔
29
                                err, ok := rvr.(error)
1✔
30
                                if !ok {
2✔
31
                                        err = fmt.Errorf("%v", rvr)
1✔
32
                                }
1✔
33
                                s.Logger.Error("panic", zap.Error(err))
1✔
34
                                w.WriteHeader(http.StatusInternalServerError)
1✔
35
                                writeJSON(w, r, errResp{
1✔
36
                                        Message: err.Error(),
1✔
37
                                        Code:    http.StatusInternalServerError,
1✔
38
                                })
1✔
39
                        }
40
                }()
41
                next.ServeHTTP(w, r)
1✔
42
        })
43
}
44

45
func pathHandler(
46
        method string, handleFuncs map[string]http.HandlerFunc,
47
) func(http.Handler) http.Handler {
1✔
48
        return func(next http.Handler) http.Handler {
2✔
49
                return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2✔
50
                        if r.Method != method {
2✔
51
                                next.ServeHTTP(w, r)
1✔
52
                                return
1✔
53
                        }
1✔
54
                        if handle, ok := handleFuncs[r.URL.Path]; ok {
1✔
NEW
UNCOV
55
                                handle(w, r)
×
NEW
UNCOV
56
                                return
×
NEW
UNCOV
57
                        }
×
58
                        next.ServeHTTP(w, r)
1✔
59
                        return
1✔
60
                })
61
        }
62
}
63

64
func stripQueryStringHandler(next http.Handler) http.Handler {
1✔
65
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2✔
66
                if r.URL.RawQuery != "" {
2✔
67
                        r.URL.RawQuery = ""
1✔
68
                        http.Redirect(w, r, r.URL.String(), http.StatusTemporaryRedirect)
1✔
69
                        return
1✔
70
                }
1✔
71
                next.ServeHTTP(w, r)
1✔
72
        })
73
}
74

75
func writeJSON(w http.ResponseWriter, r *http.Request, v interface{}) {
1✔
76
        buf, _ := json.Marshal(v)
1✔
77
        w.Header().Set("Content-Type", "application/json")
1✔
78
        w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
1✔
79
        if r.Method != http.MethodHead {
2✔
80
                _, _ = w.Write(buf)
1✔
81
        }
1✔
82
        return
1✔
83
}
84

85
type statusRecorder struct {
86
        http.ResponseWriter
87
        Status int
88
}
89

90
func (r *statusRecorder) WriteHeader(status int) {
1✔
91
        r.Status = status
1✔
92
        r.ResponseWriter.WriteHeader(status)
1✔
93
}
1✔
94

95
func (s *Server) accessLogHandler(next http.Handler) http.Handler {
1✔
96
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2✔
97
                start := time.Now()
1✔
98
                wr := &statusRecorder{
1✔
99
                        ResponseWriter: w,
1✔
100
                        Status:         200,
1✔
101
                }
1✔
102
                next.ServeHTTP(wr, r)
1✔
103
                s.Logger.Info("access",
1✔
104
                        zap.Int("status", wr.Status),
1✔
105
                        zap.String("method", r.Method),
1✔
106
                        zap.String("uri", r.URL.RequestURI()),
1✔
107
                        zap.String("ip", RealIP(r)),
1✔
108
                        zap.String("user-agent", r.UserAgent()),
1✔
109
                        zap.Duration("took", time.Since(start)),
1✔
110
                )
1✔
111
        })
1✔
112
}
113

114
type serverErrorLogWriter struct {
115
        Logger *zap.Logger
116
}
117

118
func (s *serverErrorLogWriter) Write(p []byte) (int, error) {
1✔
119
        m := string(p)
1✔
120
        if strings.HasPrefix(m, "http: TLS handshake error") && strings.HasSuffix(m, ": EOF\n") {
1✔
121
                s.Logger.Debug("server", zap.String("log", m)) // https://github.com/golang/go/issues/26918
×
122
        } else if strings.HasPrefix(m, "http: URL query contains semicolon") {
1✔
123
                s.Logger.Debug("server", zap.String("log", m)) // https://github.com/golang/go/issues/25192
×
124
        } else {
1✔
125
                s.Logger.Warn("server", zap.String("log", m))
1✔
126
        }
1✔
127
        return len(p), nil
1✔
128
}
129

130
func newServerErrorLog(logger *zap.Logger) *log.Logger {
1✔
131
        return log.New(&serverErrorLogWriter{logger}, "", 0)
1✔
132
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc