52
52
// Command line flags.
53
53
httpMethod string
54
54
postBody string
55
+ repeat int
55
56
followRedirects bool
56
57
onlyHeader bool
57
58
insecure bool
@@ -72,6 +73,7 @@ const maxRedirects = 10
72
73
func init () {
73
74
flag .StringVar (& httpMethod , "X" , "GET" , "HTTP method to use" )
74
75
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" )
75
77
flag .BoolVar (& followRedirects , "L" , false , "follow 30x redirects" )
76
78
flag .BoolVar (& onlyHeader , "I" , false , "don't read body of request" )
77
79
flag .BoolVar (& insecure , "k" , false , "allow insecure SSL connections" )
@@ -127,8 +129,11 @@ func main() {
127
129
}
128
130
129
131
url := parseURL (args [0 ])
132
+ tr := newTransport (url )
130
133
131
- visit (url )
134
+ for i := repeat + 1 ; i > 0 ; i -- {
135
+ visit (tr , url )
136
+ }
132
137
}
133
138
134
139
// readClientCert - helper function to read client certificate
@@ -197,9 +202,42 @@ func headerKeyValue(h string) (string, string) {
197
202
return strings .TrimRight (h [:i ], " " ), strings .TrimLeft (h [i :], " :" )
198
203
}
199
204
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
+
200
238
// visit visits a url and times the interaction.
201
239
// 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 ) {
203
241
req := newRequest (httpMethod , url , postBody )
204
242
205
243
var tStart , tDNSStart , tDNSEnd , tConnectStart , tConnectEnd , tTLSStart , tTLSEnd , tConnected , tTTBF , tDone time.Time
@@ -229,35 +267,6 @@ func visit(url *url.URL) {
229
267
}
230
268
req = req .WithContext (httptrace .WithClientTrace (context .Background (), trace ))
231
269
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
-
261
270
client := & http.Client {
262
271
Transport : tr ,
263
272
CheckRedirect : func (req * http.Request , via []* http.Request ) error {
@@ -363,7 +372,7 @@ func visit(url *url.URL) {
363
372
log .Fatalf ("maximum number of redirects (%d) followed" , maxRedirects )
364
373
}
365
374
366
- visit (loc )
375
+ visit (tr , loc )
367
376
}
368
377
}
369
378
0 commit comments