diff --git a/go.mod b/go.mod index 349995a..d388261 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.21.5 require ( github.com/charmbracelet/glamour v0.6.0 github.com/charmbracelet/lipgloss v0.9.1 + github.com/fullstorydev/grpcurl v1.8.9 github.com/gorilla/websocket v1.5.1 google.golang.org/grpc v1.61.0 google.golang.org/protobuf v1.32.0 @@ -16,7 +17,6 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/bufbuild/protocompile v0.6.0 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/fullstorydev/grpcurl v1.8.9 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/jhump/protoreflect v1.15.3 // indirect diff --git a/go.sum b/go.sum index 63ad1f7..61087f6 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,9 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU= github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -88,5 +89,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 814550f..8f9f565 100644 --- a/main.go +++ b/main.go @@ -63,6 +63,7 @@ func main() { headerP := flag.String("h", "", "header params") method := flag.String("m", "GET", "method request") file := flag.String("f", "", "file path") + download := flag.Bool("d", false, "download content") // GRPC exclusive flags importPath := flag.String("import-path", "", "The path to a directory from which proto sources can be imported, for use with -proto flags") @@ -118,6 +119,13 @@ func main() { return } + if *download { + err := p.Download() + if err != nil { + fmt.Println(styleErr.Render(err.Error())) + } + } + myRender, err := glamour.NewTermRenderer( glamour.WithAutoStyle(), glamour.WithWordWrap(140), diff --git a/protocol.go b/protocol.go index bc2fdc4..0fe6328 100644 --- a/protocol.go +++ b/protocol.go @@ -31,6 +31,7 @@ type Protocol interface { OnMessageReceived() PrintHeaderResponse() Close() + Download() error } type GraphQL struct { @@ -72,6 +73,7 @@ func (g *GraphQL) RequestResponse() (string, error) { } func (g *GraphQL) OnMessageReceived() {} +func (g *GraphQL) Download() error { return nil } func (g *GraphQL) PrintHeaderResponse() { printHttpResponse(g.httpResp) } @@ -175,6 +177,8 @@ func (w *Websocket) PrintHeaderResponse() { printHttpResponse(w.httpResp) } +func (w *Websocket) Download() error { return nil } + func (w *Websocket) Close() { w.client.Close() } @@ -186,6 +190,7 @@ type HTTP struct { headers string body string file string + response string } func NewHTTP(params Params) *HTTP { @@ -293,10 +298,22 @@ func (h *HTTP) RequestResponse() (string, error) { return "", err } - return string(body), nil + h.response = string(body) + + return h.response, nil } func (h *HTTP) OnMessageReceived() {} + +func (h *HTTP) Download() error { + err := saveToFile(h.response, h.url) + if err != nil { + return err + } + + return nil +} + func (h *HTTP) PrintHeaderResponse() { printHttpResponse(h.httpResp) } @@ -432,6 +449,7 @@ func (g *GRPC) RequestResponse() (string, error) { func (g *GRPC) OnMessageReceived() {} func (g *GRPC) PrintHeaderResponse() {} +func (g *GRPC) Download() error { return nil } func (g *GRPC) Close() { if g.cc != nil { @@ -472,3 +490,40 @@ func GetRandomString(length int) string { } return string(result) } + +func saveToFile(data string, urlVal string) error { + parsedURL, err := url.Parse(urlVal) + if err != nil { + return err + } + + path := parsedURL.Path + hasExtension, name := hasFileExtension(path) + + var fileName string + if hasExtension { + fileName = name + } else { + fileName = GetRandomString(10) + } + + err = os.WriteFile(fileName, []byte(data), 0644) + if err != nil { + return err + } + + return nil +} + +func hasFileExtension(path string) (bool, string) { + segments := strings.Split(path, "/") + + if len(segments) == 0 { + return false, "" + } + + lastSegment := segments[len(segments)-1] + + parts := strings.Split(lastSegment, ".") + return len(parts) >= 2, lastSegment +}