-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsup.go
151 lines (132 loc) · 4.7 KB
/
sup.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"crypto/tls"
"flag"
"fmt"
"log"
"net/http"
"net/http/httptrace"
"time"
)
func main() {
flagv := flag.Bool("v", false, "be really verbose, only do one request")
flag.Parse()
// By default log like a CLI
log.SetFlags(0)
req, err := http.NewRequest("GET", "https://"+flag.Arg(0), nil)
if err != nil {
log.Fatalf("could not build request: %v", err)
}
if *flagv {
// log with datetime in verbose mode
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
trace := verboseTrace()
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
}
t := time.NewTicker(1 * time.Second)
for {
select {
case <-t.C:
start := time.Now()
_, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
fmt.Println(time.Since(start))
}
if *flagv { // only do once for verbose
return
}
}
}
func verboseTrace() *httptrace.ClientTrace {
return &httptrace.ClientTrace{
// GetConn is called before a connection is created or
// retrieved from an idle pool. The hostPort is the
// "host:port" of the target or proxy. GetConn is called even
// if there's already an idle cached connection available.
GetConn: func(hostPort string) {
log.Printf("state: GetConn, hostPort: %q", hostPort)
},
// GotConn is called after a successful connection is
// obtained. There is no hook for failure to obtain a
// connection; instead, use the error from
// Transport.RoundTrip.
GotConn: func(info httptrace.GotConnInfo) {
log.Printf("state: GotConn, GotConnInfo: %+v", info)
},
// PutIdleConn is called when the connection is returned to
// the idle pool. If err is nil, the connection was
// successfully returned to the idle pool. If err is non-nil,
// it describes why not. PutIdleConn is not called if
// connection reuse is disabled via Transport.DisableKeepAlives.
// PutIdleConn is called before the caller's Response.Body.Close
// call returns.
// For HTTP/2, this hook is not currently used.
PutIdleConn: func(err error) {
log.Printf("state: PutIdleConn, error: %v", err)
},
// GotFirstResponseByte is called when the first byte of the response
// headers is available.
GotFirstResponseByte: func() {
log.Println("state: GotFirstResponseByte")
},
// Got100Continue is called if the server replies with a "100
// Continue" response.
Got100Continue: func() {
log.Println("state: Got100Continue")
},
// DNSStart is called when a DNS lookup begins.
DNSStart: func(info httptrace.DNSStartInfo) {
log.Printf("state: DNSStart, info: %+v", info)
},
// DNSDone is called when a DNS lookup ends.
DNSDone: func(info httptrace.DNSDoneInfo) {
log.Printf("state: DNSDone, info: %+v", info)
},
// ConnectStart is called when a new connection's Dial begins.
// If net.Dialer.DualStack (IPv6 "Happy Eyeballs") support is
// enabled, this may be called multiple times.
ConnectStart: func(network, addr string) {
log.Printf("state: ConnectStart, network: %q, addr: %q", network, addr)
},
// ConnectDone is called when a new connection's Dial
// completes. The provided err indicates whether the
// connection completedly successfully.
// If net.Dialer.DualStack ("Happy Eyeballs") support is
// enabled, this may be called multiple times.
ConnectDone: func(network, addr string, err error) {
log.Printf("state: ConnectDone, network: %q, addr: %q, err: %v", network, addr, err)
},
// TLSHandshakeStart is called when the TLS handshake is started. When
// connecting to a HTTPS site via a HTTP proxy, the handshake happens after
// the CONNECT request is processed by the proxy.
TLSHandshakeStart: func() {
log.Println("state: TLSHandshakeStart")
},
// TLSHandshakeDone is called after the TLS handshake with either the
// successful handshake's connection state, or a non-nil error on handshake
// failure.
TLSHandshakeDone: func(state tls.ConnectionState, err error) {
log.Printf("state: TLSHandshakeDone, tlsConnectionState: %+v, error: %v", state, err)
},
// WroteHeaders is called after the Transport has written
// the request headers.
WroteHeaders: func() {
log.Println("state: WroteHeaders")
},
// Wait100Continue is called if the Request specified
// "Expected: 100-continue" and the Transport has written the
// request headers but is waiting for "100 Continue" from the
// server before writing the request body.
Wait100Continue: func() {
log.Println("state: Wait100Continue")
},
// WroteRequest is called with the result of writing the
// request and any body. It may be called multiple times
// in the case of retried requests.
WroteRequest: func(info httptrace.WroteRequestInfo) {
log.Printf("state: WroteRequest, WroteRequestInfo: %+v", info)
},
}
}