Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PROD-32252] Get hey Working with CSV #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions hey.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import (
"time"

"github.com/rakyll/hey/requester"
"log"
"encoding/csv"

)

const (
Expand All @@ -49,6 +52,8 @@ var (
hostHeader = flag.String("host", "", "")
userAgent = flag.String("U", "", "")

file_name = flag.String("file_name", "", "file path to csv with one column of urls")

output = flag.String("o", "", "")

c = flag.Int("c", 50, "")
Expand All @@ -69,6 +74,7 @@ var (
var usage = `Usage: hey [options...] <url>

Options:
-file_name Path to csv file
-n Number of requests to run. Default is 200.
-c Number of workers to run concurrently. Total number of requests cannot
be smaller than the concurrency level. Default is 50.
Expand Down Expand Up @@ -112,15 +118,17 @@ func main() {
flag.Var(&hs, "H", "")

flag.Parse()
if flag.NArg() < 1 {
// We require that you are passing a file or a url to hit
if *file_name == "" && flag.NArg() < 1 {
usageAndExit("")
}

runtime.GOMAXPROCS(*cpus)
num := *n
conc := *c
q := *q
rateLimit := *q
dur := *z
fileName := *file_name

if dur > 0 {
num = math.MaxInt32
Expand All @@ -137,9 +145,7 @@ func main() {
}
}

url := flag.Args()[0]
method := strings.ToUpper(*m)

// set content-type
header := make(http.Header)
header.Set("Content-Type", *contentType)
Expand Down Expand Up @@ -190,7 +196,36 @@ func main() {
usageAndExit(err.Error())
}
}
// at this point we will read through the CSV and then use that as the url

csvfile, err := os.Open(fileName)
if err != nil {
log.Fatalln("couldnt open the csv file", err)
}
r := csv.NewReader(csvfile)
// TODO remove this after i'm done testing
break_early := true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done testing?

for {
record, err := r.Read()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check err before accessing record, which could be empty.
And make sure you handle EOF so you exit gracefully.

nurl := record[0]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nurl? Why not just url?

// ignore any strings that aren't formatted correctly
if strings.Contains(nurl, ".com") == false {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're trying to check that it's a valid URL, use url.Parse. But you could always just let it fall when it tries to connect.

continue;
}
fmt.Printf("the url is: %s\n", nurl)

//err == io.EOF or
if err != nil {
log.Fatal(err)
}
generateRequestAndGetResponse(nurl, method, username, password, *hostHeader, header, dur, bodyAll, num, conc, rateLimit, proxyURL)
if break_early {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't bother passing in hostHeader (or any other globally declared flags)

break
}
}
}

func generateRequestAndGetResponse(url string, method string, username string, password string, hostHeader string, header http.Header, dur time.Duration, bodyAll []byte, num int, conc int, rateLimit float64, proxyURL *gourl.URL) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it would repeat w.Init/w.Run for each CSV line: the approach should probably keep the initialization and start of workers as the main single execution (e.g. like worker.py in GKEmail).
I've put together an alternative hack in rakyll#245 that spins off a reader goroutine that feeds the workers urls through a shared channel.

req, err := http.NewRequest(method, url, nil)
if err != nil {
usageAndExit(err.Error())
Expand All @@ -199,12 +234,10 @@ func main() {
if username != "" || password != "" {
req.SetBasicAuth(username, password)
}

// set host header if set
if *hostHeader != "" {
req.Host = *hostHeader
if hostHeader != "" {
req.Host = hostHeader
}

ua := header.Get("User-Agent")
if ua == "" {
ua = heyUA
Expand All @@ -226,7 +259,7 @@ func main() {
RequestBody: bodyAll,
N: num,
C: conc,
QPS: q,
QPS: rateLimit,
Timeout: *t,
DisableCompression: *disableCompression,
DisableKeepAlives: *disableKeepAlives,
Expand All @@ -251,7 +284,6 @@ func main() {
}
w.Run()
}

func errAndExit(msg string) {
fmt.Fprintf(os.Stderr, msg)
fmt.Fprintf(os.Stderr, "\n")
Expand Down