-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
116 lines (96 loc) · 3.18 KB
/
main.go
File metadata and controls
116 lines (96 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"fmt"
"os"
"github.com/spf13/cobra"
"headview/network"
"headview/output"
)
const appVersion = "1.1.19"
var (
headersFlag bool
sizeFlag bool
concurrentFlag int
jsonFlag bool
csvFlag bool
)
func main() {
var rootCmd = &cobra.Command{
Use: "headview <URL>",
Short: "HTTP request timing analyzer",
Long: `headview is a command-line tool for analyzing HTTP request performance.
It performs HEAD requests and provides detailed timing information for each
step of the connection process, including DNS lookup, TCP connection,
TLS handshake, and server response times.`,
Args: cobra.ExactArgs(1),
RunE: runHeadview,
Example: ` headview https://example.com
headview https://example.com --headers
headview https://example.com --size --concurrent 10
headview https://example.com --json`,
Version: appVersion,
}
// Define flags (long flags only, no short flags for custom flags)
rootCmd.Flags().BoolVar(&headersFlag, "headers", false, "Print response headers")
rootCmd.Flags().BoolVar(&sizeFlag, "size", false, "Calculate size of page resources")
rootCmd.Flags().IntVar(&concurrentFlag, "concurrent", 5, "Maximum concurrent requests for size calculation")
rootCmd.Flags().BoolVar(&jsonFlag, "json", false, "Output in JSON format")
rootCmd.Flags().BoolVar(&csvFlag, "csv", false, "Output in CSV format")
if err := rootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
func runHeadview(cmd *cobra.Command, args []string) error {
urlArg := args[0]
// Validate URL
if urlArg == "" {
return fmt.Errorf("URL cannot be empty")
}
urlArg = network.AddDefaultProtocol(urlArg)
// Check for conflicting output formats
if jsonFlag && csvFlag {
return fmt.Errorf("cannot use both --json and --csv flags")
}
// Validate concurrent parameter
if concurrentFlag < 1 || concurrentFlag > 100 {
return fmt.Errorf("concurrent must be between 1 and 100, got %d", concurrentFlag)
}
client := network.CreateHTTPClient()
if sizeFlag {
resources, err := network.PerformGetSize(client, urlArg, concurrentFlag)
if err != nil {
return fmt.Errorf("calculating size: %w", err)
}
if jsonFlag {
output.PrintResourceSizesJSON(resources)
} else if csvFlag {
output.PrintResourceSizesCSV(resources)
} else {
output.PrintResourceSizes(resources)
}
} else {
timeStats, responses, err := network.PerformGetRequest(client, urlArg, headersFlag)
if err != nil {
return fmt.Errorf("performing request: %w", err)
}
if jsonFlag {
output.PrintTimingStatsJSON(timeStats, responses, headersFlag)
} else if csvFlag {
output.PrintTimingStatsCSV(timeStats, responses)
} else {
// Print combined response info and connection timings for each request
for i, resp := range responses {
// Print response info
output.PrintResponseInfo(resp, timeStats.CommonTimings[i].DNSLookupTime > 0, headersFlag)
// Print connection timing for this specific request
if i < len(timeStats.CommonTimings) {
output.PrintConnectionTiming(i+1, timeStats.CommonTimings[i])
}
}
// Only print combined timing stats at the end
output.PrintCombinedTimingStats(timeStats)
}
}
return nil
}