diff --git a/cmd/hspnet.go b/cmd/hspnet.go index 9051fce..fd1b4da 100644 --- a/cmd/hspnet.go +++ b/cmd/hspnet.go @@ -153,11 +153,8 @@ func StartServer(addr *hsp.Adddress) { } } -func StartSession(addr *hsp.Adddress, df *hsp.DataFormat, headerList *HeaderList) { - url := addr.String() + addr.Route - fmt.Println("Starting session on", url) - - c := client.NewClient(headerList.Map()) +func StartSession(df *hsp.DataFormat, options *client.ClientOptions) { + c := client.NewClient(options) rl, err := readline.New("> ") if err != nil { @@ -171,6 +168,13 @@ func StartSession(addr *hsp.Adddress, df *hsp.DataFormat, headerList *HeaderList }() for { + rl.SetPrompt("Route > ") + route, err := rl.Readline() + if err != nil { + break + } + + rl.SetPrompt("Data > ") line, err := rl.Readline() if err != nil { break @@ -180,7 +184,7 @@ func StartSession(addr *hsp.Adddress, df *hsp.DataFormat, headerList *HeaderList switch df.Format { case hsp.DF_TEXT: - rsp, err = c.SendText(url, line) + rsp, err = c.SendText(route, line) case hsp.DF_JSON: var data any err = json.Unmarshal([]byte(line), &data) @@ -188,9 +192,9 @@ func StartSession(addr *hsp.Adddress, df *hsp.DataFormat, headerList *HeaderList fmt.Println("ERR: Invalid JSON for request:", err) } - rsp, err = c.SendJson(url, data) + rsp, err = c.SendJson(route, data) case hsp.DF_BYTES: - rsp, err = c.SendBytes(url, []byte(line)) + rsp, err = c.SendBytes(route, []byte(line)) default: fmt.Println("ERR: Unsupported data format:", df.Format) return @@ -218,11 +222,14 @@ func main() { var dataFormat string var headerList HeaderList + var auth string flag.StringVar(&host, "host", "localhost", "specify server host") flag.StringVar(&service, "port", "998", "specify server port") flag.StringVar(&address, "addr", "localhost:998", "specify target address") + flag.StringVar(&auth, "auth", "", "provide auth credentials") + flag.Var(&headerList, "H", "provide additional header") flag.StringVar(&dataFormat, "format", "text", "specify request's data format") @@ -241,12 +248,6 @@ func main() { return } - addr, err := hsp.ParseAddress(address) - if err != nil { - fmt.Printf("ERR: Invalid address %s: %v\n", address, err) - return - } - var df *hsp.DataFormat switch dataFormat { @@ -260,5 +261,11 @@ func main() { fmt.Println("ERR: Invalid format selected for requests:", dataFormat) } - StartSession(addr, df, &headerList) + options := &client.ClientOptions{ + Headers: headerList.Map(), + Auth: auth, + BaseURL: address, + } + + StartSession(df, options) } diff --git a/hsp/address.go b/hsp/address.go index a062665..aee1a82 100644 --- a/hsp/address.go +++ b/hsp/address.go @@ -7,18 +7,18 @@ import ( type Adddress struct { Host string - Port string + Port string Route string } func ParseAddress(address string) (*Adddress, error) { - parts := strings.SplitN(address, "/", 2) + parts := strings.Split(address, "/") var route string if len(parts) == 1 { route = "/" } else if len(parts) > 1 { - route = "/" + strings.Join(parts[1:], "") + route = "/" + strings.Join(parts[1:], "/") } else { return nil, fmt.Errorf("Failed to parse address: %s", address) } @@ -30,18 +30,29 @@ func ParseAddress(address string) (*Adddress, error) { if strings.Contains(addr, ":") { p := strings.Split(addr, ":") if len(p) >= 2 { - port = p[len(p) - 1] + port = p[len(p)-1] addr = p[0] } } return &Adddress{ Host: addr, - Port: port, + Port: port, Route: route, }, nil } +func (a *Adddress) Extend(extension string) (*Adddress, error) { + route := strings.TrimRight(a.Route, "/") + ext := strings.TrimLeft(extension, "/") + + return &Adddress{ + Host: a.Host, + Port: a.Port, + Route: route + "/" + ext, + }, nil +} + func (a *Adddress) String() string { return fmt.Sprintf("%s:%s", a.Host, a.Port) } diff --git a/hsp/client/client.go b/hsp/client/client.go index 2e0d336..095eb93 100644 --- a/hsp/client/client.go +++ b/hsp/client/client.go @@ -4,32 +4,59 @@ import ( "encoding/json" "fmt" "io" + "maps" "net" "github.com/LandaMm/hsp-go/hsp" ) -type Client struct { +type ClientOptions struct { Headers map[string]string + // TODO: in future support multiple types of auth (credentials, key etc.) + Auth string + BaseURL string } -func NewClient(headers map[string]string) *Client { +type Client struct { + Options *ClientOptions + Base *hsp.Adddress +} + +func NewClient(options *ClientOptions) *Client { + if options == nil { + options = &ClientOptions{} + } + + var base *hsp.Adddress + + if len(options.BaseURL) > 0 { + addr, err := hsp.ParseAddress(options.BaseURL) + if err == nil { + base = addr + } + } + return &Client{ - Headers: headers, + Options: options, + Base: base, } } func (c *Client) BuildHeaders(address *hsp.Adddress, df *hsp.DataFormat) map[string]string { headers := make(map[string]string) - if len(c.Headers) > 0 { - maps.Copy(headers, c.Headers) + if len(c.Options.Headers) > 0 { + maps.Copy(headers, c.Options.Headers) } headers[hsp.H_ROUTE] = address.Route headers[hsp.H_DATA_FORMAT] = df.String() + if len(c.Options.Auth) > 0 { + headers[hsp.H_AUTH] = c.Options.Auth + } + return headers } @@ -75,7 +102,14 @@ func (c *Client) SingleHit(addr *hsp.Adddress, pkt *hsp.Packet) (*hsp.Packet, er } func (c *Client) SendText(address, text string) (*hsp.Response, error) { - addr, err := hsp.ParseAddress(address) + var addr *hsp.Adddress + var err error + + if c.Base != nil { + addr, err = c.Base.Extend(address) + } else { + addr, err = hsp.ParseAddress(address) + } if err != nil { return nil, err @@ -96,7 +130,14 @@ func (c *Client) SendText(address, text string) (*hsp.Response, error) { } func (c *Client) SendJson(address string, data any) (*hsp.Response, error) { - addr, err := hsp.ParseAddress(address) + var addr *hsp.Adddress + var err error + + if c.Base != nil { + addr, err = c.Base.Extend(address) + } else { + addr, err = hsp.ParseAddress(address) + } if err != nil { return nil, err @@ -120,7 +161,14 @@ func (c *Client) SendJson(address string, data any) (*hsp.Response, error) { } func (c *Client) SendBytes(address string, data []byte) (*hsp.Response, error) { - addr, err := hsp.ParseAddress(address) + var addr *hsp.Adddress + var err error + + if c.Base != nil { + addr, err = c.Base.Extend(address) + } else { + addr, err = hsp.ParseAddress(address) + } if err != nil { return nil, err