From b7ac3bc5491fe4dff7d15821c3f33f884741d419 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:05:50 +0400 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=94=A8=20update=20CLIYesOrNoReader=20?= =?UTF-8?q?to=20include=20default=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readers/cli.go | 20 ++++++++++++++++++-- requests/requests.go | 4 +++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/readers/cli.go b/readers/cli.go index 8f90cc5..542525b 100644 --- a/readers/cli.go +++ b/readers/cli.go @@ -75,11 +75,27 @@ func CLIConfigReader() (*config.CLIConfig, error) { return cliConfig, nil } -func CLIYesOrNoReader(message string) bool { +// CLIYesOrNoReader reads a yes or no answer from the command line. +// It prompts the user with the given message and default value, +// and returns true if the user answers "y" or "Y", and false otherwise. +// If there is an error while reading the input, it returns false. +// If the user simply presses enter without providing any input, +// it returns the default value specified by the `dft` parameter. +func CLIYesOrNoReader(message string, dft bool) bool { var answer string - fmt.Printf("%s [y/N]: ", message) + defaultMessage := "Y/n" + if !dft { + defaultMessage = "y/N" + } + fmt.Printf("%s [%s]: ", message, defaultMessage) if _, err := fmt.Scanln(&answer); err != nil { + if err.Error() == "unexpected newline" { + return dft + } return false } + if answer == "" { + return dft + } return answer == "y" || answer == "Y" } diff --git a/requests/requests.go b/requests/requests.go index 55106bc..d4ed843 100644 --- a/requests/requests.go +++ b/requests/requests.go @@ -272,7 +272,9 @@ func getClientDoFunc( } activeProxyClientsCount := len(activeProxyClients) var yesOrNoMessage string + var yesOrNoDefault bool if activeProxyClientsCount == 0 { + yesOrNoDefault = false yesOrNoMessage = utils.Colored( utils.Colors.Red, "No active proxies found. Do you want to continue?", @@ -287,7 +289,7 @@ func getClientDoFunc( ) } fmt.Println() - proceed := readers.CLIYesOrNoReader(yesOrNoMessage) + proceed := readers.CLIYesOrNoReader(yesOrNoMessage, yesOrNoDefault) if !proceed { utils.PrintAndExit("Exiting...") } From c2ce8e587bccb5e42da55b73ab54d15f43887497 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:06:49 +0400 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=94=A8=20add=20CLI=20yes=20or=20no=20?= =?UTF-8?q?reader=20to=20confirm=20starting=20Dodo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main.go b/main.go index faa6a9d..9482c1a 100644 --- a/main.go +++ b/main.go @@ -81,6 +81,12 @@ func main() { Body: jsonConf.Body, } dodoConf.Print() + response := readers.CLIYesOrNoReader("Do you want to continue?", true) + if response { + utils.PrintlnC(utils.Colors.Green, "Starting Dodo\n") + } else { + utils.PrintAndExit("Exiting...") + } ctx, cancel := context.WithCancel(context.Background()) sigChan := make(chan os.Signal, 1) From 75ada96d35509ef3728905a23e825cb74a64c173 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:09:00 +0400 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=8E=A8=20auto=20formatted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requests/requests.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/requests/requests.go b/requests/requests.go index d4ed843..46976b2 100644 --- a/requests/requests.go +++ b/requests/requests.go @@ -518,7 +518,7 @@ func getSharedRandomClientDoFunc( clientsCount int, timeout time.Duration, ) ClientDoFunc { - return func (ctx context.Context, request *fasthttp.Request) (*fasthttp.Response, error) { + return func(ctx context.Context, request *fasthttp.Request) (*fasthttp.Response, error) { client := &clients[rand.Intn(clientsCount)] defer client.CloseIdleConnections() response := fasthttp.AcquireResponse() @@ -550,16 +550,17 @@ func getSharedRandomClientDoFunc( // The function internally creates a new response using fasthttp.AcquireResponse() and a channel to handle errors. // It then spawns a goroutine to execute the client.DoTimeout() method with the given request, response, and timeout. // The function uses a select statement to handle three cases: -// - If an error is received from the channel, it checks if the error is not nil. If it's not nil, it releases the response and returns nil and the error. -// Otherwise, it returns the response and nil. -// - If the timeout duration is reached, it releases the response and returns nil and a custom timeout error. -// - If the context is canceled, it returns nil and a custom interrupt error. +// - If an error is received from the channel, it checks if the error is not nil. If it's not nil, it releases the response and returns nil and the error. +// Otherwise, it returns the response and nil. +// - If the timeout duration is reached, it releases the response and returns nil and a custom timeout error. +// - If the context is canceled, it returns nil and a custom interrupt error. +// // The function ensures that idle connections are closed by calling client.CloseIdleConnections() using a defer statement. func getSharedClientDoFunc( client *fasthttp.HostClient, timeout time.Duration, ) ClientDoFunc { - return func (ctx context.Context, request *fasthttp.Request) (*fasthttp.Response, error) { + return func(ctx context.Context, request *fasthttp.Request) (*fasthttp.Response, error) { defer client.CloseIdleConnections() response := fasthttp.AcquireResponse() ch := make(chan error) From ff1df870aa15068c47d9f127f345f0e04974c686 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:26:32 +0400 Subject: [PATCH 4/6] =?UTF-8?q?=E2=9C=A8=20add=20yes=20flag=20to=20CLIConf?= =?UTF-8?q?igReader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.go | 2 ++ main.go | 19 +++++++++++-------- readers/cli.go | 2 ++ requests/requests.go | 13 ++++++++----- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/config/config.go b/config/config.go index 93c033f..a75b576 100644 --- a/config/config.go +++ b/config/config.go @@ -35,6 +35,7 @@ type RequestConfig struct { Cookies map[string]string Proxies []Proxy Body string + Yes bool } func (config *RequestConfig) Print() { @@ -152,6 +153,7 @@ func (config *JSONConfig) MergeConfigs(newConfig *JSONConfig) { type CLIConfig struct { Config + Yes bool `json:"yes" validate:"omitempty"` ConfigFile string `validation_name:"config-file" validate:"omitempty,filepath"` } diff --git a/main.go b/main.go index 9482c1a..d4b1991 100644 --- a/main.go +++ b/main.go @@ -68,7 +68,7 @@ func main() { if err != nil { utils.PrintErrAndExit(err) } - dodoConf := &config.RequestConfig{ + requestConf := &config.RequestConfig{ Method: conf.Method, URL: parsedURL, Timeout: time.Duration(conf.Timeout) * time.Millisecond, @@ -79,13 +79,16 @@ func main() { Cookies: jsonConf.Cookies, Proxies: jsonConf.Proxies, Body: jsonConf.Body, + Yes: cliConf.Yes, } - dodoConf.Print() - response := readers.CLIYesOrNoReader("Do you want to continue?", true) - if response { - utils.PrintlnC(utils.Colors.Green, "Starting Dodo\n") - } else { - utils.PrintAndExit("Exiting...") + requestConf.Print() + if !cliConf.Yes { + response := readers.CLIYesOrNoReader("Do you want to continue?", true) + if response { + utils.PrintlnC(utils.Colors.Green, "Starting Dodo\n") + } else { + utils.PrintAndExit("Exiting...") + } } ctx, cancel := context.WithCancel(context.Background()) @@ -96,7 +99,7 @@ func main() { cancel() }() - responses, err := requests.Run(ctx, dodoConf) + responses, err := requests.Run(ctx, requestConf) if err != nil { if customerrors.Is(err, customerrors.ErrInterrupt) { utils.PrintlnC(utils.Colors.Yellow, err.Error()) diff --git a/readers/cli.go b/readers/cli.go index 542525b..82ed597 100644 --- a/readers/cli.go +++ b/readers/cli.go @@ -14,6 +14,7 @@ func CLIConfigReader() (*config.CLIConfig, error) { var ( returnNil = false cliConfig = &config.CLIConfig{} + // y bool dodosCount int requestCount int timeout int @@ -45,6 +46,7 @@ func CLIConfigReader() (*config.CLIConfig, error) { ) rootCmd.Flags().StringVarP(&cliConfig.ConfigFile, "config-file", "c", "", "Path to the config file") + rootCmd.Flags().BoolVarP(&cliConfig.Yes, "yes", "y", false, "Answer yes to all questions") rootCmd.Flags().StringVarP(&cliConfig.Method, "method", "m", "", fmt.Sprintf("HTTP Method (default %s)", config.DefaultMethod)) rootCmd.Flags().StringVarP(&cliConfig.URL, "url", "u", "", "URL for stress testing") rootCmd.Flags().IntVarP(&dodosCount, "dodos-count", "d", config.DefaultDodosCount, "Number of dodos(threads)") diff --git a/requests/requests.go b/requests/requests.go index 46976b2..83c1d40 100644 --- a/requests/requests.go +++ b/requests/requests.go @@ -110,6 +110,7 @@ func Run(ctx context.Context, requestConfig *config.RequestConfig) (Responses, e requestConfig.Timeout, requestConfig.Proxies, requestConfig.GetValidDodosCountForProxies(), + requestConfig.Yes, requestConfig.URL, ) if clientDoFunc == nil { @@ -260,6 +261,7 @@ func getClientDoFunc( timeout time.Duration, proxies []config.Proxy, dodosCount int, + yes bool, URL *url.URL, ) ClientDoFunc { isTLS := URL.Scheme == "https" @@ -276,7 +278,7 @@ func getClientDoFunc( if activeProxyClientsCount == 0 { yesOrNoDefault = false yesOrNoMessage = utils.Colored( - utils.Colors.Red, + utils.Colors.Yellow, "No active proxies found. Do you want to continue?", ) } else { @@ -288,10 +290,11 @@ func getClientDoFunc( ), ) } - fmt.Println() - proceed := readers.CLIYesOrNoReader(yesOrNoMessage, yesOrNoDefault) - if !proceed { - utils.PrintAndExit("Exiting...") + if !yes { + response := readers.CLIYesOrNoReader("\n" + yesOrNoMessage, yesOrNoDefault) + if !response { + utils.PrintAndExit("Exiting...") + } } fmt.Println() if activeProxyClientsCount == 0 { From 8b59dcfda4982c3c51f42ca84d60576def7bc6fb Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:26:58 +0400 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=9A=20Update=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4cc7901..58b8992 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ docker run --rm -v ./path/config.json:/dodo/config.json -i aykhans/dodo -u https | Parameter | JSON config file | CLI Flag | CLI Short Flag | Type | Description | Default | | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | | Config file | - | --config-file | -c | String | Path to the JSON config file | - | +| Yes | - | --yes | -y | Boolean | Answer yes to all questions | false | | URL | url | --url | -u | String | URL to send the request to | - | | Method | method | --method | -m | String | HTTP method | GET | | Request count | request_count | --request-count | -r | Integer | Total number of requests to send | 1000 | From 1690cd72c0111c2f810c7e6c37f5d618f2b47be6 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Tue, 3 Sep 2024 02:29:05 +0400 Subject: [PATCH 6/6] =?UTF-8?q?=20=F0=9F=8E=A8=20auto=20formatted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readers/cli.go | 1 - requests/requests.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/readers/cli.go b/readers/cli.go index 82ed597..920613d 100644 --- a/readers/cli.go +++ b/readers/cli.go @@ -14,7 +14,6 @@ func CLIConfigReader() (*config.CLIConfig, error) { var ( returnNil = false cliConfig = &config.CLIConfig{} - // y bool dodosCount int requestCount int timeout int diff --git a/requests/requests.go b/requests/requests.go index 83c1d40..9272e90 100644 --- a/requests/requests.go +++ b/requests/requests.go @@ -291,7 +291,7 @@ func getClientDoFunc( ) } if !yes { - response := readers.CLIYesOrNoReader("\n" + yesOrNoMessage, yesOrNoDefault) + response := readers.CLIYesOrNoReader("\n"+yesOrNoMessage, yesOrNoDefault) if !response { utils.PrintAndExit("Exiting...") }