106 lines
2.0 KiB
Go
106 lines
2.0 KiB
Go
package httping
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptrace"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/net/http/httpproxy"
|
|
)
|
|
|
|
type Stats struct {
|
|
Proxy bool
|
|
Scheme string
|
|
DNS int64
|
|
TCP int64
|
|
TLS int64
|
|
Process int64
|
|
Transfer int64
|
|
Total int64
|
|
}
|
|
|
|
func New(address string) (Stats, error) {
|
|
var err error
|
|
var stats Stats
|
|
var t0, t1, t2, t3, t4, t5, t6, t7 int64
|
|
|
|
req, _ := http.NewRequest("GET", address, nil)
|
|
trace := &httptrace.ClientTrace{
|
|
DNSStart: func(info httptrace.DNSStartInfo) {
|
|
t0 = time.Now().UnixNano()
|
|
},
|
|
DNSDone: func(info httptrace.DNSDoneInfo) {
|
|
t1 = time.Now().UnixNano()
|
|
if info.Err != nil {
|
|
err = info.Err
|
|
log.Fatal(info.Err)
|
|
}
|
|
},
|
|
ConnectStart: func(net, addr string) {
|
|
},
|
|
ConnectDone: func(net, addr string, err error) {
|
|
if err != nil {
|
|
log.Fatalf("unable to connect to host %v: %v", addr, err)
|
|
}
|
|
t2 = time.Now().UnixNano()
|
|
},
|
|
GotConn: func(info httptrace.GotConnInfo) {
|
|
t3 = time.Now().UnixNano()
|
|
},
|
|
GotFirstResponseByte: func() {
|
|
t4 = time.Now().UnixNano()
|
|
},
|
|
TLSHandshakeStart: func() {
|
|
t5 = time.Now().UnixNano()
|
|
},
|
|
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
|
|
t6 = time.Now().UnixNano()
|
|
},
|
|
}
|
|
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
|
|
c := &http.Client{
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
_, err = c.Do(req)
|
|
if err != nil {
|
|
match, _ := regexp.MatchString("Client.Timeout exceeded", err.Error())
|
|
if match {
|
|
log.Fatal("Connection timeout")
|
|
} else {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
t7 = time.Now().UnixNano()
|
|
|
|
if strings.HasPrefix(address, "http://") {
|
|
stats.Scheme = "http"
|
|
} else if strings.HasPrefix(address, "https://") {
|
|
stats.Scheme = "https"
|
|
}
|
|
|
|
if t0 == 0 {
|
|
t0 = t2
|
|
t1 = t2
|
|
}
|
|
|
|
stats.DNS = t1 - t0
|
|
stats.TCP = t2 - t1
|
|
stats.Process = t4 - t3
|
|
stats.Transfer = t7 - t4
|
|
stats.TLS = t6 - t5
|
|
stats.Total = t7 - t0
|
|
|
|
// Detect proxies
|
|
pc := httpproxy.FromEnvironment()
|
|
if pc.HTTPProxy != "" {
|
|
stats.Proxy = true
|
|
}
|
|
|
|
return stats, err
|
|
}
|