diff --git a/config/config.go b/config/config.go index ed492a5..57fcaba 100644 --- a/config/config.go +++ b/config/config.go @@ -11,7 +11,7 @@ import ( const ( VERSION = "0.0.1" DefaultUserAgent = "Dodo/" + VERSION - ProxyCheckURL = "https://google.com" + ProxyCheckURL = "https://www.google.com" DefaultMethod = "GET" DefaultTimeout = 10000 // Milliseconds (10 seconds) DefaultDodosCount = 1 @@ -23,8 +23,6 @@ type IConfig interface { MergeConfigs(newConfig IConfig) IConfig } -type ProxySlice []map[string]string - type DodoConfig struct { Method string URL string @@ -34,7 +32,7 @@ type DodoConfig struct { Params map[string]string Headers map[string]string Cookies map[string]string - Proxies ProxySlice + Proxies []Proxy Body string } @@ -98,12 +96,18 @@ func (config *Config) SetDefaults() { } } +type Proxy struct { + URL string `json:"url" validate:"required,proxy_url"` + Username string `json:"username"` + Password string `json:"password"` +} + type JSONConfig struct { Config Params map[string]string `json:"params"` Headers map[string]string `json:"headers"` Cookies map[string]string `json:"cookies"` - Proxies ProxySlice `json:"proxies" validate:"url_map_slice"` + Proxies []Proxy `json:"proxies" validate:"dive"` Body string `json:"body"` } diff --git a/custom_errors/formaters.go b/custom_errors/formaters.go index df383c5..c877a7c 100644 --- a/custom_errors/formaters.go +++ b/custom_errors/formaters.go @@ -6,7 +6,6 @@ import ( "net/url" "strings" - "github.com/aykhans/dodo/config" "github.com/go-playground/validator/v10" ) @@ -24,36 +23,34 @@ func CobraErrorFormater(err error) error { return err } +func shortenNamespace(namespace string) string { + return namespace[strings.Index(namespace, ".")+1:] +} + func ValidationErrorsFormater(errs validator.ValidationErrors) error { errsStr := make(map[string]string) for _, err := range errs { switch err.Tag() { case "required": - errsStr[err.Field()] = fmt.Sprintf("Field \"%s\" is required", err.Field()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Field \"%s\" is required", err.Field()) case "gte": - errsStr[err.Field()] = fmt.Sprintf("Value of \"%s\" must be greater than or equal to \"%s\"", err.Field(), err.Param()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Value of \"%s\" must be greater than or equal to \"%s\"", err.Field(), err.Param()) case "lte": - errsStr[err.Field()] = fmt.Sprintf("Value of \"%s\" must be less than or equal to \"%s\"", err.Field(), err.Param()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Value of \"%s\" must be less than or equal to \"%s\"", err.Field(), err.Param()) case "filepath": - errsStr[err.Field()] = fmt.Sprintf("Invalid file path for \"%s\" field: \"%s\"", err.Field(), err.Value()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Invalid file path for \"%s\" field: \"%s\"", err.Field(), err.Value()) case "http_url": - errsStr[err.Field()] = fmt.Sprintf("Invalid URL for \"%s\" field: \"%s\"", err.Field(), err.Value()) + errsStr[shortenNamespace(err.Namespace())] = + fmt.Sprintf("Invalid url for \"%s\" field: \"%s\"", err.Field(), err.Value()) // --------------------------------------| Custom validations |-------------------------------------- case "http_method": - errsStr[err.Field()] = fmt.Sprintf("Invalid HTTP method for \"%s\" field: \"%s\"", err.Field(), err.Value()) - case "url_map_slice": - values := err.Value().(config.ProxySlice) - for i, value := range values { - if _, ok := value["url"]; !ok { - errsStr[fmt.Sprintf("%s[%d]", err.Field(), i)] = fmt.Sprintf("Field \"url\" is required for \"%s\" field", err.Field()) - } else { - errsStr[fmt.Sprintf("%s[%d]", err.Field(), i)] = fmt.Sprintf("Invalid url for \"%s\" field: \"%s\"", err.Field(), value["url"]) - } - } + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Invalid HTTP method for \"%s\" field: \"%s\"", err.Field(), err.Value()) + case "proxy_url": + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Invalid proxy url for \"%s\" field: \"%s\" (it must be http, socks5 or socks5h)", err.Field(), err.Value()) case "string_bool": - errsStr[err.Field()] = fmt.Sprintf("Invalid value for \"%s\" field: \"%s\"", err.Field(), err.Value()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Invalid value for \"%s\" field: \"%s\"", err.Field(), err.Value()) default: - errsStr[err.Field()] = fmt.Sprintf("Invalid value for \"%s\" field: \"%s\"", err.Field(), err.Value()) + errsStr[shortenNamespace(err.Namespace())] = fmt.Sprintf("Invalid value for \"%s\" field: \"%s\"", err.Field(), err.Value()) } } return NewValidationErrors(errsStr, errs) diff --git a/main.go b/main.go index 5bc9ff5..2dd0ea7 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "os" + "strings" "time" "github.com/aykhans/dodo/config" @@ -35,7 +36,11 @@ func main() { if err != nil { utils.PrintErrAndExit(err) } - if err := validator.StructPartial(jsonConfNew, "Proxies"); err != nil { + if err := validator.StructFiltered( + jsonConfNew, + func(ns []byte) bool { + return strings.LastIndex(string(ns), "Proxies") == -1 + }); err != nil { utils.PrintErrAndExit( customerrors.ValidationErrorsFormater( err.(goValidator.ValidationErrors), diff --git a/requests/requests.go b/requests/requests.go index 1f64589..b1ce006 100644 --- a/requests/requests.go +++ b/requests/requests.go @@ -268,13 +268,13 @@ func printProgress(wg *sync.WaitGroup, total int, message string, countSlice *[] pw.Stop() } -func getClientFunc(proxies config.ProxySlice, timeout time.Duration, dodosCount int) func() http.Client { +func getClientFunc(proxies []config.Proxy, timeout time.Duration, dodosCount int) func() http.Client { if len(proxies) > 0 { activeProxyClientsArray := make([][]http.Client, dodosCount) proxiesCount := len(proxies) var wg sync.WaitGroup wg.Add(dodosCount + 1) - var proxiesSlice config.ProxySlice + var proxiesSlice []config.Proxy countSlice := make([]int, dodosCount) go printProgress(&wg, proxiesCount, "Searching for active proxies🌐", &countSlice) @@ -330,7 +330,7 @@ func getClientFunc(proxies config.ProxySlice, timeout time.Duration, dodosCount } func findActiveProxyClients( - proxies config.ProxySlice, + proxies []config.Proxy, timeout time.Duration, activeProxyClients *[]http.Client, counter *int, @@ -365,12 +365,12 @@ func findActiveProxyClients( } } -func getTransport(proxy map[string]string) (*http.Transport, error) { - proxyURL, err := url.Parse(proxy["url"]) +func getTransport(proxy config.Proxy) (*http.Transport, error) { + proxyURL, err := url.Parse(proxy.URL) if err != nil { return nil, err } - if _, ok := proxy["username"]; !ok { + if proxy.Username != "" { transport := &http.Transport{ Proxy: http.ProxyURL(proxyURL), } @@ -382,7 +382,7 @@ func getTransport(proxy map[string]string) (*http.Transport, error) { &url.URL{ Scheme: proxyURL.Scheme, Host: proxyURL.Host, - User: url.UserPassword(proxy["username"], proxy["password"]), + User: url.UserPassword(proxy.Username, proxy.Password), }, ), } diff --git a/validation/validator.go b/validation/validator.go index da27b9f..948c48d 100644 --- a/validation/validator.go +++ b/validation/validator.go @@ -4,7 +4,6 @@ import ( "reflect" "strings" - "github.com/aykhans/dodo/config" "github.com/go-playground/validator/v10" "golang.org/x/net/http/httpguts" ) @@ -39,16 +38,19 @@ func NewValidator() *validator.Validate { }, ) validation.RegisterValidation( - "url_map_slice", + "proxy_url", func(fl validator.FieldLevel) bool { - proxies := fl.Field().Interface().(config.ProxySlice) - for _, proxy := range proxies { - if _, ok := proxy["url"]; !ok { - return false - } - if err := validation.Var(proxy["url"], "url"); err != nil { - return false - } + url := fl.Field().String() + if url == "" { + return false + } + if err := validation.Var(url, "url"); err != nil { + return false + } + if !(url[:7] == "http://" || + url[:9] == "socks5://" || + url[:10] == "socks5h://") { + return false } return true },