-
Notifications
You must be signed in to change notification settings - Fork 14
/
main.go
129 lines (114 loc) · 3.3 KB
/
main.go
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
117
118
119
120
121
122
123
124
125
126
127
128
129
package main
import (
"bufio"
"bytes"
"crypto/tls"
"flag"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/valyala/fasthttp"
)
var averageTime time.Duration
var numOfSuccess int32
var numOfFail int32
var numOfnon200 int32
var mtx sync.Mutex
var urlStr string
func sendRequest(client *fasthttp.Client, req *fasthttp.Request, wg *sync.WaitGroup, timeout int) {
defer wg.Done()
for {
resp := fasthttp.AcquireResponse()
timeStart := time.Now()
err := client.DoTimeout(req, resp, time.Duration(timeout)*time.Second)
if err != nil {
atomic.AddInt32(&numOfFail, 1)
continue
}
go setAvarageTime(averageTime + time.Since(timeStart))
if resp.StatusCode() == fasthttp.StatusOK {
atomic.AddInt32(&numOfSuccess, 1)
} else {
atomic.AddInt32(&numOfnon200, 1)
}
}
}
func setAvarageTime(newTime time.Duration) {
mtx.Lock()
averageTime = newTime
mtx.Unlock()
}
func main() {
requestFile := flag.String("r", "", "Path of request file")
numWorker := flag.Int("w", 500, "Number of worker. Default: 500")
duration := flag.Int("d", 0, "Test duration. Default: infinite")
timeout := flag.Int("t", 5, "HTTP request timeout (sec.)")
https := flag.Bool("https", true, "Enable https protocol")
flag.Parse()
if *requestFile == "" {
fmt.Println("Please specify all arguments!")
flag.PrintDefaults()
os.Exit(1) // Exit condition requires non-zero exit code
}
content, err := ioutil.ReadFile(*requestFile)
if err != nil {
panic(err)
}
httpRequest, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(content)))
if err != nil && err != io.ErrUnexpectedEOF {
panic(err)
}
var wg sync.WaitGroup
urlStr = "http://" + httpRequest.Host + httpRequest.RequestURI
if *https {
urlStr = "https://" + httpRequest.Host + httpRequest.RequestURI
}
bodyBytes, err := ioutil.ReadAll(httpRequest.Body)
if err != nil {
panic(err)
}
req := fasthttp.AcquireRequest()
req.SetRequestURI(urlStr)
req.Header.SetMethod(httpRequest.Method)
if httpRequest.Method == "POST" {
req.SetBody(bodyBytes)
}
for key, element := range httpRequest.Header {
req.Header.Set(key, strings.Join(element, ","))
}
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Content-Length", string(rune(httpRequest.ContentLength)))
client := &fasthttp.Client{
TLSConfig: &tls.Config{InsecureSkipVerify: true},
}
fmt.Println("Starting the action...")
fmt.Println("The request will be sent:")
fmt.Println("_________________________________")
fmt.Println(string(content))
fmt.Println("_________________________________")
for i := 0; i < *numWorker; i++ {
wg.Add(1)
go sendRequest(client, req, &wg, *timeout)
}
if *duration != 0 {
time.Sleep(time.Duration(*duration) * time.Second)
fmt.Println("")
fmt.Println("---------Results--------------------")
fmt.Println("")
fmt.Println("Total Requests Sent:", numOfSuccess+numOfnon200+numOfFail)
fmt.Println("Number of 200OK Responses:", numOfSuccess)
fmt.Println("Number of non-200OK Responses:", numOfnon200)
fmt.Println("Number of Failed Responses:", numOfFail)
fmt.Println("Avg. Response Time:", averageTime/time.Duration(numOfSuccess+numOfnon200+numOfFail))
os.Exit(0) // Exit without error
}
fmt.Println("Infinite mode is active. No output will be shown..")
wg.Wait()
}