-
-
Notifications
You must be signed in to change notification settings - Fork 143
/
logclient.go
115 lines (90 loc) · 2.45 KB
/
logclient.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package update
import (
"bytes"
"fmt"
"io"
"net/http"
"strings"
"github.com/qdm12/ddns-updater/internal/provider/utils"
)
//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . DebugLogger
type DebugLogger interface {
Debug(s string)
}
func makeLogClient(client *http.Client, logger DebugLogger) (newClient *http.Client) {
newClient = &http.Client{
Timeout: client.Timeout,
}
originalTransport := client.Transport
if originalTransport == nil {
originalTransport = http.DefaultTransport
}
transport, ok := originalTransport.(*http.Transport)
if !ok {
panic(fmt.Sprintf("transport %T is not *http.Transport", originalTransport))
}
clonedTransport := transport.Clone()
newClient.Transport = &loggingRoundTripper{
proxied: clonedTransport,
logger: logger,
}
return newClient
}
type loggingRoundTripper struct {
proxied http.RoundTripper
logger DebugLogger
}
func (lrt *loggingRoundTripper) RoundTrip(request *http.Request) (
response *http.Response, err error) {
lrt.logger.Debug(requestToString(request))
response, err = lrt.proxied.RoundTrip(request)
if err != nil {
return response, err
}
lrt.logger.Debug(responseToString(response))
return response, nil
}
func requestToString(request *http.Request) (s string) {
s = request.Method + " " + request.URL.String()
if request.Header != nil {
s += " | headers: " + headerToString(request.Header)
}
if request.Body != nil {
newBody, bodyString := readAndResetBody(request.Body)
request.Body = newBody
s += " | body: " + bodyString
}
return s
}
func responseToString(response *http.Response) (s string) {
s = response.Status
if response.Header != nil {
s += " | headers: " + headerToString(response.Header)
}
if response.Body != nil {
newBody, bodyString := readAndResetBody(response.Body)
response.Body = newBody
s += " | body: " + bodyString
}
return s
}
func headerToString(header http.Header) (s string) {
headers := make([]string, 0, len(header))
for key, values := range header {
headerString := key + ": " + strings.Join(values, ",")
headers = append(headers, headerString)
}
return strings.Join(headers, "; ")
}
func readAndResetBody(body io.ReadCloser) (
newBody io.ReadCloser, bodyString string) {
b, err := io.ReadAll(body)
if err != nil {
bodyString = "error reading body: " + err.Error()
} else {
bodyString = utils.ToSingleLine(string(b))
_ = body.Close()
newBody = io.NopCloser(bytes.NewBuffer(b))
}
return newBody, bodyString
}