mirror of
https://github.com/aykhans/dodo.git
synced 2025-04-16 01:43:13 +00:00
- Moved readers to the config package - Added an option to read remote config files - Moved the validation package to the config package and removed the validator dependency - Moved the customerrors package to the config package - Replaced fatih/color with jedib0t/go-pretty/v6/text - Removed proxy check functionality - Added param, header, cookie, body, and proxy flags to the CLI - Allowed multiple values for the same key in params, headers, and cookies
176 lines
5.4 KiB
Go
176 lines
5.4 KiB
Go
package config
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/aykhans/dodo/types"
|
|
"github.com/aykhans/dodo/utils"
|
|
)
|
|
|
|
const cliUsageText = `Usage:
|
|
dodo [flags]
|
|
|
|
Examples:
|
|
|
|
Simple usage only with URL:
|
|
dodo -u https://example.com
|
|
|
|
Usage with config file:
|
|
dodo -f /path/to/config/file/config.json
|
|
|
|
Usage with all flags:
|
|
dodo -f /path/to/config/file/config.json \
|
|
-u https://example.com -m POST \
|
|
-d 10 -r 1000 -t 3s \
|
|
-b "body1" -body "body2" \
|
|
-H "header1: value1" -header "header2: value2" \
|
|
-p "param1=value1" -param "param2=value2" \
|
|
-c "cookie1=value1" -cookie "cookie2=value2" \
|
|
-x "http://proxy.example.com:8080" -proxy "socks5://proxy2.example.com:8080" \
|
|
-y
|
|
|
|
Flags:
|
|
-h, -help help for dodo
|
|
-v, -version version for dodo
|
|
-y, -yes bool Answer yes to all questions (default %v)
|
|
-f, -config-file string Path to the local config file or http(s) URL of the config file
|
|
-d, -dodos uint Number of dodos(threads) (default %d)
|
|
-r, -requests uint Number of total requests (default %d)
|
|
-t, -timeout Duration Timeout for each request (e.g. 400ms, 15s, 1m10s) (default %v)
|
|
-u, -url string URL for stress testing
|
|
-m, -method string HTTP Method for the request (default %s)
|
|
-b, -body [string] Body for the request (e.g. "body text")
|
|
-p, -param [string] Parameter for the request (e.g. "key1=value1")
|
|
-H, -header [string] Header for the request (e.g. "key1: value1")
|
|
-c, -cookie [string] Cookie for the request (e.g. "key1=value1")
|
|
-x, -proxy [string] Proxy for the request (e.g. "http://proxy.example.com:8080")`
|
|
|
|
func (config *Config) ReadCLI() (types.ConfigFile, error) {
|
|
flag.Usage = func() {
|
|
fmt.Printf(
|
|
cliUsageText+"\n",
|
|
DefaultYes,
|
|
DefaultDodosCount,
|
|
DefaultRequestCount,
|
|
DefaultTimeout,
|
|
DefaultMethod,
|
|
)
|
|
}
|
|
|
|
var (
|
|
version = false
|
|
configFile = ""
|
|
yes = false
|
|
method = ""
|
|
url types.RequestURL
|
|
dodosCount = uint(0)
|
|
requestCount = uint(0)
|
|
timeout time.Duration
|
|
)
|
|
|
|
{
|
|
flag.BoolVar(&version, "version", false, "Prints the version of the program")
|
|
flag.BoolVar(&version, "v", false, "Prints the version of the program")
|
|
|
|
flag.StringVar(&configFile, "config-file", "", "Path to the configuration file")
|
|
flag.StringVar(&configFile, "f", "", "Path to the configuration file")
|
|
|
|
flag.BoolVar(&yes, "yes", false, "Answer yes to all questions")
|
|
flag.BoolVar(&yes, "y", false, "Answer yes to all questions")
|
|
|
|
flag.StringVar(&method, "method", "", "HTTP Method")
|
|
flag.StringVar(&method, "m", "", "HTTP Method")
|
|
|
|
flag.Var(&url, "url", "URL to send the request")
|
|
flag.Var(&url, "u", "URL to send the request")
|
|
|
|
flag.UintVar(&dodosCount, "dodos", 0, "Number of dodos(threads)")
|
|
flag.UintVar(&dodosCount, "d", 0, "Number of dodos(threads)")
|
|
|
|
flag.UintVar(&requestCount, "requests", 0, "Number of total requests")
|
|
flag.UintVar(&requestCount, "r", 0, "Number of total requests")
|
|
|
|
flag.DurationVar(&timeout, "timeout", 0, "Timeout for each request (e.g. 400ms, 15s, 1m10s)")
|
|
flag.DurationVar(&timeout, "t", 0, "Timeout for each request (e.g. 400ms, 15s, 1m10s)")
|
|
|
|
flag.Var(&config.Params, "param", "URL parameter to send with the request")
|
|
flag.Var(&config.Params, "p", "URL parameter to send with the request")
|
|
|
|
flag.Var(&config.Headers, "header", "Header to send with the request")
|
|
flag.Var(&config.Headers, "H", "Header to send with the request")
|
|
|
|
flag.Var(&config.Cookies, "cookie", "Cookie to send with the request")
|
|
flag.Var(&config.Cookies, "c", "Cookie to send with the request")
|
|
|
|
flag.Var(&config.Body, "body", "Body to send with the request")
|
|
flag.Var(&config.Body, "b", "Body to send with the request")
|
|
|
|
flag.Var(&config.Proxies, "proxy", "Proxy to use for the request")
|
|
flag.Var(&config.Proxies, "x", "Proxy to use for the request")
|
|
}
|
|
|
|
flag.Parse()
|
|
|
|
if len(os.Args) <= 1 {
|
|
flag.CommandLine.Usage()
|
|
os.Exit(0)
|
|
}
|
|
|
|
if args := flag.Args(); len(args) > 0 {
|
|
return types.ConfigFile(configFile), fmt.Errorf("unexpected arguments: %v", strings.Join(args, ", "))
|
|
}
|
|
|
|
if version {
|
|
fmt.Printf("dodo version %s\n", VERSION)
|
|
os.Exit(0)
|
|
}
|
|
|
|
flag.Visit(func(f *flag.Flag) {
|
|
switch f.Name {
|
|
case "method", "m":
|
|
config.Method = utils.ToPtr(method)
|
|
case "url", "u":
|
|
config.URL = utils.ToPtr(url)
|
|
case "dodos", "d":
|
|
config.DodosCount = utils.ToPtr(dodosCount)
|
|
case "requests", "r":
|
|
config.RequestCount = utils.ToPtr(requestCount)
|
|
case "timeout", "t":
|
|
config.Timeout = &types.Timeout{Duration: timeout}
|
|
case "yes", "y":
|
|
config.Yes = utils.ToPtr(yes)
|
|
}
|
|
})
|
|
|
|
return types.ConfigFile(configFile), nil
|
|
}
|
|
|
|
// 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
|
|
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"
|
|
}
|