diff --git a/cmd/url-parser/main.go b/cmd/url-parser/main.go index c775c79..9123e1e 100644 --- a/cmd/url-parser/main.go +++ b/cmd/url-parser/main.go @@ -2,7 +2,9 @@ package main import ( "fmt" + "io" "os" + "strings" "github.com/sirupsen/logrus" "github.com/thegeeklab/url-parser/command" @@ -21,19 +23,25 @@ func main() { fmt.Printf("%s version=%s date=%s\n", c.App.Name, c.App.Version, BuildDate) } - config := &config.Config{} + cfg := &config.Config{} app := &cli.App{ Name: "url-parser", Usage: "Parse URL and shows the part of it.", Version: BuildVersion, - Action: command.Run(config), + Action: command.Run(cfg), Flags: []cli.Flag{ &cli.StringFlag{ Name: "url", Usage: "source url to parse", EnvVars: []string{"URL_PARSER_URL"}, - Destination: &config.URL, + Destination: &cfg.URL, + }, + &cli.BoolFlag{ + Name: "stdin", + Usage: "read url to parse from stdin", + EnvVars: []string{"URL_PARSER_STDIN"}, + Destination: &cfg.Stdin, }, }, Commands: []*cli.Command{ @@ -41,59 +49,89 @@ func main() { Name: "all", Aliases: []string{"a"}, Usage: "Get all parts from url", - Action: command.Run(config), + Action: command.Run(cfg), }, { Name: "scheme", Aliases: []string{"s"}, Usage: "Get scheme from url", - Action: command.Scheme(config), + Action: command.Scheme(cfg), }, { Name: "user", Aliases: []string{"u"}, Usage: "Get username from url", - Action: command.User(config), + Action: command.User(cfg), }, { Name: "password", Aliases: []string{"pw"}, Usage: "Get password from url", - Action: command.Password(config), + Action: command.Password(cfg), }, { Name: "path", Aliases: []string{"pt"}, Usage: "Get path from url", - Action: command.Path(config), - Flags: command.PathFlags(config), + Action: command.Path(cfg), + Flags: command.PathFlags(cfg), }, { Name: "host", Aliases: []string{"h"}, Usage: "Get hostname from url", - Action: command.Host(config), + Action: command.Host(cfg), }, { Name: "port", Aliases: []string{"p"}, Usage: "Get port from url", - Action: command.Port(config), + Action: command.Port(cfg), }, { Name: "query", Aliases: []string{"q"}, Usage: "Get query from url", - Action: command.Query(config), - Flags: command.QueryFlags(config), + Action: command.Query(cfg), + Flags: command.QueryFlags(cfg), }, { Name: "fragment", Aliases: []string{"f"}, Usage: "Get fragment from url", - Action: command.Fragment(config), + Action: command.Fragment(cfg), }, }, + Before: func(ctx *cli.Context) error { + if cfg.URL == "" && !cfg.Stdin { + _ = cli.ShowAppHelp(ctx) + + return fmt.Errorf("error: %w", config.ErrRequiredFlagsNotSet) + } + + if cfg.URL != "" && cfg.Stdin { + _ = cli.ShowAppHelp(ctx) + + return fmt.Errorf("error: %w", config.ErrExclusiveFlags) + } + + if cfg.Stdin { + stat, _ := os.Stdin.Stat() + if (stat.Mode() & os.ModeCharDevice) == 0 { + stdin, err := io.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("error: %w: %w", config.ErrEmptyStdin, err) + } + cfg.URL = strings.TrimSuffix(string(stdin), "\n") + } + + if cfg.URL == "" { + return fmt.Errorf("error: %w", config.ErrEmptyStdin) + } + } + + return nil + }, } if err := app.Run(os.Args); err != nil { diff --git a/command/commands.go b/command/commands.go index 7137296..040acd8 100644 --- a/command/commands.go +++ b/command/commands.go @@ -1,10 +1,12 @@ package command import ( + "fmt" "net/url" "strings" "github.com/sirupsen/logrus" + "github.com/thegeeklab/url-parser/config" ) func parseURL(raw string) *url.URL { @@ -12,7 +14,7 @@ func parseURL(raw string) *url.URL { url, err := url.Parse(urlString) if err != nil { - logrus.Fatal(err) + logrus.Fatal(fmt.Errorf("%w: %w", config.ErrParseURL, err)) } return url diff --git a/config/config.go b/config/config.go index e81b56f..7ba2a90 100644 --- a/config/config.go +++ b/config/config.go @@ -1,7 +1,18 @@ package config +import "errors" + +var ( + ErrRequiredFlagsNotSet = errors.New("either \"url\" or \"stdin\" must be set") + ErrExclusiveFlags = errors.New("\"url\" and \"stdin\" are mutually exclusive") + ErrEmptyStdin = errors.New("\"stdin\" must not be empty") + ErrReadStdin = errors.New("failed to read \"stdin\"") + ErrParseURL = errors.New("failed to parse url") +) + type Config struct { URL string + Stdin bool QueryField string PathIndex int }