Skip to content

Commit 29f4578

Browse files
committed
initial import
1 parent c6c3f64 commit 29f4578

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# httpstat
2+
3+
Immitation is the most sincere form of flattery.
4+
5+
## We don't need no stinking curl
6+
7+
`httpstat.py` is a wrapper around `curl(1)`, which is all fine and good, but what if you don't have `curl(1)` or `python(1)` installed?

main.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"flag"
6+
"fmt"
7+
"io"
8+
"io/ioutil"
9+
"log"
10+
"net"
11+
"net/http"
12+
"net/url"
13+
"os"
14+
"strings"
15+
"time"
16+
)
17+
18+
const (
19+
HTTPS_TEMPLATE = `` +
20+
` DNS Lookup TCP Connection SSL Handshake Server Processing Content Transfer` +
21+
`[ {a0000} | {a0001} | {a0002} | {a0003} | {a0004} ]` +
22+
` | | | | |` +
23+
` namelookup:{b0000} | | | |` +
24+
` connect:{b0001} | | |` +
25+
` pretransfer:{b0002} | |` +
26+
` starttransfer:{b0003} |` +
27+
` total:{b0004}`
28+
29+
HTTP_TEMPLATE = `` +
30+
` DNS Lookup TCP Connection Server Processing Content Transfer` + "\n" +
31+
`[ %7dms | %7dms | %7dms | %7dms ]` + "\n" +
32+
` | | | |` + "\n" +
33+
` namelookup:%7dms | | |` + "\n" +
34+
` connect:%7dms | |` + "\n" +
35+
` starttransfer:%7dms |` + "\n" +
36+
` total:%7dms` + "\n"
37+
)
38+
39+
func main() {
40+
flag.Parse()
41+
42+
args := flag.Args()
43+
if len(args) != 1 {
44+
log.Fatalf("usage: %s URL", os.Args[0])
45+
}
46+
47+
url, err := url.Parse(args[0])
48+
if err != nil {
49+
log.Fatalf("could not parse url %q: %v", args[0], err)
50+
}
51+
52+
scheme := url.Scheme
53+
hostport := url.Host
54+
host, port := func() (string, int) {
55+
switch scheme {
56+
case "https":
57+
return hostport, 443
58+
case "http":
59+
return hostport, 80
60+
default:
61+
log.Fatalf("unsupported url scheme %q", scheme)
62+
return "", 0 // not reached
63+
}
64+
}()
65+
66+
t0 := time.Now() // before dns resolution
67+
raddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", host, port))
68+
if err != nil {
69+
log.Fatalf("unable to resolve host: %v", err)
70+
}
71+
72+
t1 := time.Now() // after dns resolution, before connect
73+
conn, err := net.DialTCP("tcp", nil, raddr)
74+
if err != nil {
75+
log.Fatalf("unable to connect to host %vv %v", raddr, err)
76+
}
77+
78+
t2 := time.Now() // after connect, before request
79+
req, err := http.NewRequest("GET", url.String(), nil)
80+
if err != nil {
81+
log.Fatalf("unable to create request: %v", err)
82+
}
83+
84+
if err := req.Write(conn); err != nil {
85+
log.Fatalf("failed to write request: %v", err)
86+
}
87+
88+
t3 := time.Now() // after request, before read response
89+
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
90+
if err != nil {
91+
log.Fatalf("failed to read response: %v", err)
92+
}
93+
94+
t4 := time.Now() // after read request, before read body
95+
if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
96+
log.Fatalf("failed to read response body: %v", err)
97+
}
98+
99+
t5 := time.Now() // after read body
100+
resp.Body.Close()
101+
102+
_ = t3
103+
104+
// print status line and headers
105+
fmt.Println("\n", resp.Proto, resp.Status)
106+
107+
for k, v := range resp.Header {
108+
fmt.Println(k+":", strings.Join(v, ","))
109+
}
110+
111+
fmt.Println("\nBody discarded\n")
112+
113+
switch scheme {
114+
case "https":
115+
case "http":
116+
fmt.Printf(HTTP_TEMPLATE,
117+
int(t1.Sub(t0)/time.Millisecond), // dns lookup
118+
int(t2.Sub(t1)/time.Millisecond), // tcp connection
119+
int(t4.Sub(t2)/time.Millisecond), // server processing
120+
int(t5.Sub(t4)/time.Millisecond), // content transfer
121+
int(t1.Sub(t0)/time.Millisecond), // namelookup
122+
int(t2.Sub(t0)/time.Millisecond), // connect
123+
int(t4.Sub(t0)/time.Millisecond), // starttransfer
124+
int(t5.Sub(t0)/time.Millisecond), // total
125+
)
126+
127+
}
128+
}

0 commit comments

Comments
 (0)