Skip to content

Commit

Permalink
Add repeat option support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rs committed Apr 27, 2018
1 parent a8a8dc0 commit a278fa1
Showing 1 changed file with 41 additions and 32 deletions.
73 changes: 41 additions & 32 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ var (
// Command line flags.
httpMethod string
postBody string
repeat int
followRedirects bool
onlyHeader bool
insecure bool
Expand All @@ -72,6 +73,7 @@ const maxRedirects = 10
func init() {
flag.StringVar(&httpMethod, "X", "GET", "HTTP method to use")
flag.StringVar(&postBody, "d", "", "the body of a POST or PUT request; from file use @filename")
flag.IntVar(&repeat, "r", 0, "Repeat the same request N times on the same connection")
flag.BoolVar(&followRedirects, "L", false, "follow 30x redirects")
flag.BoolVar(&onlyHeader, "I", false, "don't read body of request")
flag.BoolVar(&insecure, "k", false, "allow insecure SSL connections")
Expand Down Expand Up @@ -127,8 +129,11 @@ func main() {
}

url := parseURL(args[0])
tr := newTransport(url)

visit(url)
for i := repeat + 1; i > 0; i-- {
visit(tr, url)
}
}

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

func newTransport(url *url.URL) *http.Transport {
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}

switch url.Scheme {
case "https":
host, _, err := net.SplitHostPort(url.Host)
if err != nil {
host = url.Host
}

tr.TLSClientConfig = &tls.Config{
ServerName: host,
InsecureSkipVerify: insecure,
Certificates: readClientCert(clientCertFile),
}

// Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.
// See https://github.com/golang/go/issues/14275
err = http2.ConfigureTransport(tr)
if err != nil {
log.Fatalf("failed to prepare transport for HTTP/2: %v", err)
}
}

return tr
}

// visit visits a url and times the interaction.
// If the response is a 30x, visit follows the redirect.
func visit(url *url.URL) {
func visit(tr *http.Transport, url *url.URL) {
req := newRequest(httpMethod, url, postBody)

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

tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}

switch url.Scheme {
case "https":
host, _, err := net.SplitHostPort(req.Host)
if err != nil {
host = req.Host
}

tr.TLSClientConfig = &tls.Config{
ServerName: host,
InsecureSkipVerify: insecure,
Certificates: readClientCert(clientCertFile),
}

// Because we create a custom TLSClientConfig, we have to opt-in to HTTP/2.
// See https://github.com/golang/go/issues/14275
err = http2.ConfigureTransport(tr)
if err != nil {
log.Fatalf("failed to prepare transport for HTTP/2: %v", err)
}
}

client := &http.Client{
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
Expand Down Expand Up @@ -363,7 +372,7 @@ func visit(url *url.URL) {
log.Fatalf("maximum number of redirects (%d) followed", maxRedirects)
}

visit(loc)
visit(tr, loc)
}
}

Expand Down

0 comments on commit a278fa1

Please sign in to comment.