Skip to content

Commit a278fa1

Browse files
committed
Add repeat option support
Add an option to repeat the same request multiple times, reusing the same HTTP connection. To have accurate measurement of TLS and support skipped steps (DNS, TCP and TLS reuse), the timing code has been refactored to use Go 1.8 support for TLS tracing as well as a more descriptive variable namings for steps time. This commit removes support for Go versions lower than 1.8.
1 parent a8a8dc0 commit a278fa1

File tree

1 file changed

+41
-32
lines changed

1 file changed

+41
-32
lines changed

main.go

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ var (
5252
// Command line flags.
5353
httpMethod string
5454
postBody string
55+
repeat int
5556
followRedirects bool
5657
onlyHeader bool
5758
insecure bool
@@ -72,6 +73,7 @@ const maxRedirects = 10
7273
func init() {
7374
flag.StringVar(&httpMethod, "X", "GET", "HTTP method to use")
7475
flag.StringVar(&postBody, "d", "", "the body of a POST or PUT request; from file use @filename")
76+
flag.IntVar(&repeat, "r", 0, "Repeat the same request N times on the same connection")
7577
flag.BoolVar(&followRedirects, "L", false, "follow 30x redirects")
7678
flag.BoolVar(&onlyHeader, "I", false, "don't read body of request")
7779
flag.BoolVar(&insecure, "k", false, "allow insecure SSL connections")
@@ -127,8 +129,11 @@ func main() {
127129
}
128130

129131
url := parseURL(args[0])
132+
tr := newTransport(url)
130133

131-
visit(url)
134+
for i := repeat + 1; i > 0; i-- {
135+
visit(tr, url)
136+
}
132137
}
133138

134139
// readClientCert - helper function to read client certificate
@@ -197,9 +202,42 @@ func headerKeyValue(h string) (string, string) {
197202
return strings.TrimRight(h[:i], " "), strings.TrimLeft(h[i:], " :")
198203
}
199204

205+
func newTransport(url *url.URL) *http.Transport {
206+
tr := &http.Transport{
207+
Proxy: http.ProxyFromEnvironment,
208+
MaxIdleConns: 100,
209+
IdleConnTimeout: 90 * time.Second,
210+
TLSHandshakeTimeout: 10 * time.Second,
211+
ExpectContinueTimeout: 1 * time.Second,
212+
}
213+
214+
switch url.Scheme {
215+
case "https":
216+
host, _, err := net.SplitHostPort(url.Host)
217+
if err != nil {
218+
host = url.Host
219+
}
220+
221+
tr.TLSClientConfig = &tls.Config{
222+
ServerName: host,
223+
InsecureSkipVerify: insecure,
224+
Certificates: readClientCert(clientCertFile),
225+
}
226+
227+
// Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.
228+
// See https://github.com/golang/go/issues/14275
229+
err = http2.ConfigureTransport(tr)
230+
if err != nil {
231+
log.Fatalf("failed to prepare transport for HTTP/2: %v", err)
232+
}
233+
}
234+
235+
return tr
236+
}
237+
200238
// visit visits a url and times the interaction.
201239
// If the response is a 30x, visit follows the redirect.
202-
func visit(url *url.URL) {
240+
func visit(tr *http.Transport, url *url.URL) {
203241
req := newRequest(httpMethod, url, postBody)
204242

205243
var tStart, tDNSStart, tDNSEnd, tConnectStart, tConnectEnd, tTLSStart, tTLSEnd, tConnected, tTTBF, tDone time.Time
@@ -229,35 +267,6 @@ func visit(url *url.URL) {
229267
}
230268
req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
231269

232-
tr := &http.Transport{
233-
Proxy: http.ProxyFromEnvironment,
234-
MaxIdleConns: 100,
235-
IdleConnTimeout: 90 * time.Second,
236-
TLSHandshakeTimeout: 10 * time.Second,
237-
ExpectContinueTimeout: 1 * time.Second,
238-
}
239-
240-
switch url.Scheme {
241-
case "https":
242-
host, _, err := net.SplitHostPort(req.Host)
243-
if err != nil {
244-
host = req.Host
245-
}
246-
247-
tr.TLSClientConfig = &tls.Config{
248-
ServerName: host,
249-
InsecureSkipVerify: insecure,
250-
Certificates: readClientCert(clientCertFile),
251-
}
252-
253-
// Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.
254-
// See https://github.com/golang/go/issues/14275
255-
err = http2.ConfigureTransport(tr)
256-
if err != nil {
257-
log.Fatalf("failed to prepare transport for HTTP/2: %v", err)
258-
}
259-
}
260-
261270
client := &http.Client{
262271
Transport: tr,
263272
CheckRedirect: func(req *http.Request, via []*http.Request) error {
@@ -363,7 +372,7 @@ func visit(url *url.URL) {
363372
log.Fatalf("maximum number of redirects (%d) followed", maxRedirects)
364373
}
365374

366-
visit(loc)
375+
visit(tr, loc)
367376
}
368377
}
369378

0 commit comments

Comments
 (0)