Gist: Estimate a remote server's HTTP read-timeout in Go
Example Go code to estimate the read-header timeout of a remote HTTP server.
Last updated on: 2025-06-08
package main
import (
"context"
"fmt"
"io"
"net"
"os"
"strconv"
"time"
)
func main() {
targetNetAddr := "127.0.0.1:8080"
targetHTTPHost := "example.org"
sourceIPAddr := net.IP{127, 0, 0, 1}
ua := "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
slowThrottle := time.Second
fmt.Printf("Starting header-read timeout estimate...\n")
fmt.Printf("- Targetting: %s\n", targetNetAddr)
fmt.Printf("- With HTTP Host: %s\n", targetHTTPHost)
fmt.Printf("- From: %s\n", sourceIPAddr)
fmt.Printf("\n")
netDialer := &net.Dialer{LocalAddr: &net.TCPAddr{IP: sourceIPAddr}, Timeout: time.Second}
conn, err := netDialer.DialContext(context.Background(), "tcp", targetNetAddr)
if err != nil {
fmt.Printf("Failed to establish TCP connection: %s\n", err)
os.Exit(1)
}
readTimeoutEstimateStart := time.Now()
_, err = io.WriteString(conn, "GET / HTTP/1.1"+"\r\n"+
"Host: "+targetHTTPHost+"\r\n"+
"User-Agent: "+ua+"\r\n")
if err != nil {
fmt.Printf("Failed to write beginning of HTTP request: %s\n", err)
os.Exit(1)
}
for i := 0; true; i++ {
_, err = io.WriteString(conn, "X-"+strconv.Itoa(i)+": foo"+"\r\n")
if err != nil {
break
}
elapsed := time.Since(readTimeoutEstimateStart)
fmt.Printf("Wrote slow header #%d (%s elapsed)\n", i, fmt.Sprintf("%.1fs", elapsed.Seconds()))
if elapsed > time.Minute {
fmt.Printf("Timeout is more than 1 minute!\n")
break
}
time.Sleep(slowThrottle)
}
estimatedTimeout := time.Since(readTimeoutEstimateStart) - slowThrottle
fmt.Printf("Estimated header-read timeout: %s\n", fmt.Sprintf("%.1fs", estimatedTimeout.Seconds()))
}