From 0fe782c768fc4d1f05d4ce45fc77f6fad7989ff0 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Fri, 20 Dec 2024 01:20:45 +0400 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=94=A8=20Add=20'PrettyJSONMarshal'=20?= =?UTF-8?q?function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/convert.go | 106 ++++++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/utils/convert.go b/utils/convert.go index 4017861..76bf424 100644 --- a/utils/convert.go +++ b/utils/convert.go @@ -6,49 +6,77 @@ import ( "reflect" ) -func MarshalJSON(v any, maxSliceSize uint) string { - rv := reflect.ValueOf(v) - if rv.Kind() == reflect.Slice && rv.Len() == 0 { - return "[]" - } - - data, err := json.MarshalIndent(truncateLists(v, int(maxSliceSize)), "", " ") - if err != nil { - return "{}" - } - - return string(data) +type TruncatedMarshaller struct { + Value interface{} + MaxItems int } -func truncateLists(v interface{}, maxItems int) interface{} { - rv := reflect.ValueOf(v) +func (t TruncatedMarshaller) MarshalJSON() ([]byte, error) { + val := reflect.ValueOf(t.Value) - switch rv.Kind() { - case reflect.Slice, reflect.Array: - if rv.Len() > maxItems { - newSlice := reflect.MakeSlice(rv.Type(), maxItems, maxItems) - reflect.Copy(newSlice, rv.Slice(0, maxItems)) - newSlice = reflect.Append(newSlice, reflect.ValueOf(fmt.Sprintf("...(%d more)", rv.Len()-maxItems))) - return newSlice.Interface() - } + if val.Kind() != reflect.Slice && val.Kind() != reflect.Array { + return json.Marshal(t.Value) + } + + length := val.Len() + if length <= t.MaxItems { + return json.Marshal(t.Value) + } + + truncated := make([]interface{}, t.MaxItems+1) + + for i := 0; i < t.MaxItems; i++ { + truncated[i] = val.Index(i).Interface() + } + + remaining := length - t.MaxItems + truncated[t.MaxItems] = fmt.Sprintf("+%d", remaining) + + return json.Marshal(truncated) +} + +func PrettyJSONMarshal(v interface{}, maxItems int, prefix, indent string) []byte { + truncated := processValue(v, maxItems) + d, _ := json.MarshalIndent(truncated, prefix, indent) + return d +} + +func processValue(v interface{}, maxItems int) interface{} { + val := reflect.ValueOf(v) + + switch val.Kind() { case reflect.Map: - newMap := reflect.MakeMap(rv.Type()) - for _, key := range rv.MapKeys() { - newMap.SetMapIndex(key, reflect.ValueOf(truncateLists(rv.MapIndex(key).Interface(), maxItems))) + newMap := make(map[string]interface{}) + iter := val.MapRange() + for iter.Next() { + k := iter.Key().String() + newMap[k] = processValue(iter.Value().Interface(), maxItems) } - return newMap.Interface() - case reflect.Struct: - newStruct := reflect.New(rv.Type()).Elem() - for i := 0; i < rv.NumField(); i++ { - newStruct.Field(i).Set(reflect.ValueOf(truncateLists(rv.Field(i).Interface(), maxItems))) - } - return newStruct.Interface() - case reflect.Ptr: - if rv.IsNil() { - return nil - } - return truncateLists(rv.Elem().Interface(), maxItems) - } + return newMap - return v + case reflect.Slice, reflect.Array: + return TruncatedMarshaller{Value: v, MaxItems: maxItems} + + case reflect.Struct: + newMap := make(map[string]interface{}) + t := val.Type() + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + if field.IsExported() { + jsonTag := field.Tag.Get("json") + if jsonTag == "-" { + continue + } + fieldName := field.Name + if jsonTag != "" { + fieldName = jsonTag + } + newMap[fieldName] = processValue(val.Field(i).Interface(), maxItems) + } + } + return newMap + + default: + return v + } } From d2bd60e3ff2718ff276050585a9e6c8716054e19 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Fri, 20 Dec 2024 01:21:26 +0400 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=94=A8=20Add=20custom=20'WidthMaxEnfo?= =?UTF-8?q?rcer'=20to=20the=20table=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.go | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/config/config.go b/config/config.go index 9015f8a..1a87700 100644 --- a/config/config.go +++ b/config/config.go @@ -1,9 +1,9 @@ package config import ( - "fmt" "net/url" "os" + "strings" "time" . "github.com/aykhans/dodo/types" @@ -42,7 +42,18 @@ func (config *RequestConfig) Print() { t.SetOutputMirror(os.Stdout) t.SetStyle(table.StyleLight) t.SetColumnConfigs([]table.ColumnConfig{ - {Number: 2, WidthMax: 50}, + { + Number: 2, + WidthMaxEnforcer: func(col string, maxLen int) string { + lines := strings.Split(col, "\n") + for i, line := range lines { + if len(line) > maxLen { + lines[i] = line[:maxLen-3] + "..." + } + } + return strings.Join(lines, "\n") + }, + WidthMax: 50}, }) newHeaders := make(map[string][]string) @@ -56,23 +67,23 @@ func (config *RequestConfig) Print() { t.AppendSeparator() t.AppendRow(table.Row{"URL", config.URL}) t.AppendSeparator() - t.AppendRow(table.Row{"Timeout", fmt.Sprintf("%dms", config.Timeout/time.Millisecond)}) + t.AppendRow(table.Row{"Timeout", config.Timeout}) t.AppendSeparator() t.AppendRow(table.Row{"Dodos", config.DodosCount}) t.AppendSeparator() t.AppendRow(table.Row{"Requests", config.RequestCount}) t.AppendSeparator() - t.AppendRow(table.Row{"Params", utils.MarshalJSON(config.Params, 3)}) + t.AppendRow(table.Row{"Params", string(utils.PrettyJSONMarshal(config.Params, 3, "", " "))}) t.AppendSeparator() - t.AppendRow(table.Row{"Headers", utils.MarshalJSON(newHeaders, 3)}) + t.AppendRow(table.Row{"Headers", string(utils.PrettyJSONMarshal(newHeaders, 3, "", " "))}) t.AppendSeparator() - t.AppendRow(table.Row{"Cookies", utils.MarshalJSON(config.Cookies, 3)}) + t.AppendRow(table.Row{"Cookies", string(utils.PrettyJSONMarshal(config.Cookies, 3, "", " "))}) t.AppendSeparator() - t.AppendRow(table.Row{"Proxies Count", len(config.Proxies)}) + t.AppendRow(table.Row{"Proxies Count", string(utils.PrettyJSONMarshal(config.Proxies, 3, "", " "))}) t.AppendSeparator() t.AppendRow(table.Row{"Proxy Check", !config.NoProxyCheck}) t.AppendSeparator() - t.AppendRow(table.Row{"Body", utils.MarshalJSON(config.Body, 3)}) + t.AppendRow(table.Row{"Body", string(utils.PrettyJSONMarshal(config.Body, 3, "", " "))}) t.Render() } From efc4c62001105d740539ffb4e448c78d93b13519 Mon Sep 17 00:00:00 2001 From: Aykhan Shahsuvarov Date: Fri, 20 Dec 2024 18:16:25 +0400 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9A=20Update=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8d160be..efbb09d 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,9 @@ You can find an example config structure in the [config.json](https://github.com "method": "GET", "url": "https://example.com", "no_proxy_check": false, - "timeout": 10000, - "dodos_count": 1, - "request_count": 1, + "timeout": 2000, + "dodos_count": 10, + "request_count": 1000, "params": {}, "headers": {}, "cookies": {},