-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathhttp.go
106 lines (92 loc) · 2.77 KB
/
http.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
package gubrak
import (
"io"
"net/http"
"net/http/httptrace"
"time"
)
// Client http client wrapper
type Client struct {
httpClient *http.Client
}
// NewClient function for intialize Client object
// Paramter, timeout in time.Duration
func NewClient(timeout time.Duration) *Client {
return &Client{
httpClient: &http.Client{Timeout: time.Second * timeout},
}
}
// request function for initalize http request,
// paramters, http method, uri path, body, and headers
func (c *Client) request(method string, fullPath string, body io.Reader, headers map[string]string) (*http.Request, error) {
req, err := http.NewRequest(method, fullPath, body)
if err != nil {
return nil, err
}
for key, value := range headers {
req.Header.Set(key, value)
}
return req, nil
}
// Do function for call http request
func (c *Client) do(method, path string, body io.Reader, headers map[string]string) (*Trace, error) {
start := time.Now()
req, err := c.request(method, path, body, headers)
if err != nil {
return nil, err
}
var dnsDuration, connDuration, resDuration, reqDuration, delayDuration time.Duration
var dnsStartTime, connectionStartTime, reqStartTime, delayStartTime, gotResultTime time.Time
traceConfig := &httptrace.ClientTrace{
DNSStart: func(info httptrace.DNSStartInfo) {
dnsStartTime = time.Now()
},
DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
dnsDuration = time.Since(dnsStartTime)
},
GetConn: func(h string) {
connectionStartTime = time.Now()
},
GotConn: func(connInfo httptrace.GotConnInfo) {
if !connInfo.Reused {
connDuration = time.Since(connectionStartTime)
}
reqStartTime = time.Now()
},
WroteRequest: func(w httptrace.WroteRequestInfo) {
reqDuration = time.Since(reqStartTime)
delayStartTime = time.Now()
},
GotFirstResponseByte: func() {
delayDuration = time.Since(delayStartTime)
gotResultTime = time.Now()
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), traceConfig))
res, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
finish := time.Since(start)
resDuration = time.Since(gotResultTime)
tracingResult := &Trace{
HTTPResponse: res,
Duration: finish,
ConnDuration: connDuration,
DNSDuration: dnsDuration,
ReqDuration: reqDuration,
ResDuration: resDuration,
DelayDuration: delayDuration,
}
return tracingResult, nil
}
// Trace represent the struct of tracing data
type Trace struct {
HTTPResponse *http.Response
Duration time.Duration
ConnDuration time.Duration // connection setup(DNS lookup + Dial up) duration
DNSDuration time.Duration // dns lookup duration
ReqDuration time.Duration // request "write" duration
ResDuration time.Duration // response "read" duration
DelayDuration time.Duration // delay between response and request
}