Skip to content

Commit

Permalink
feat(apiclient): support bulk parameter in api commands using slices
Browse files Browse the repository at this point in the history
  • Loading branch information
KaiSchwarz-cnic committed Mar 13, 2020
1 parent bf01b4a commit c11db41
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 108 deletions.
78 changes: 69 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ package main

import (
"fmt"

CL "github.com/hexonet/go-sdk/apiclient"
)

Expand All @@ -72,10 +72,9 @@ func main() {
// or r := cl.Login("12345678") // provide here your 2FA otp code
if r.IsSuccess() {
fmt.Println("Login succeeded.")
cmd := map[string]string{
"COMMAND": "StatusAccount",
}
r = cl.Request(cmd)
r = cl.Request(map[string]interface{}{
"COMMAND": "StatusAccount"
})
if r.IsSuccess() {
fmt.Println("Command succeeded.")
r = cl.Logout()
Expand All @@ -100,7 +99,7 @@ package main

import (
"fmt"

CL "github.com/hexonet/go-sdk/apiclient"
)

Expand All @@ -110,10 +109,71 @@ func main() {
cl.SetRemoteIPAddress("1.2.3.4")
//cl.SetOTP("12345678") to provide your 2FA otp code
cl.UseOTESystem()
cmd := map[string]string{
"COMMAND": "StatusAccount",
r := cl.Request(map[string]interface{}{
"COMMAND": "StatusAccount"
})
if r.IsSuccess() {
fmt.Println("Command succeeded.")
} else {
fmt.Println("Command failed.")
}
}
```

#### Using Bulk Parameters in API Command

Of course, you could do the following:

```go
package main

import (
"fmt"

CL "github.com/hexonet/go-sdk/apiclient"
)

func main() {
cl := CL.NewAPIClient()
cl.SetCredentials("test.user", "test.passw0rd")
cl.SetRemoteIPAddress("1.2.3.4")
cl.UseOTESystem()
r := cl.Request(map[string]interface{}{
"COMMAND": "QueryDomainOptions",
"DOMAIN0": "example1.com";
"DOMAIN1": "example2.com";
})
if r.IsSuccess() {
fmt.Println("Command succeeded.")
} else {
fmt.Println("Command failed.")
}
r := cl.Request(cmd)
}
```

but probably better:

```go
package main

import (
"fmt"

CL "github.com/hexonet/go-sdk/apiclient"
)

func main() {
cl := CL.NewAPIClient()
cl.SetCredentials("test.user", "test.passw0rd")
cl.SetRemoteIPAddress("1.2.3.4")
cl.UseOTESystem()
r := cl.Request(map[string]interface{}{
"COMMAND": "QueryDomainOptions",
"DOMAIN": []string{
"example1.com",
"example2.com"
}
})
if r.IsSuccess() {
fmt.Println("Command succeeded.")
} else {
Expand Down
65 changes: 46 additions & 19 deletions apiclient/apiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import (
"io/ioutil"
"net/http"
"net/url"
"reflect"
"runtime"
"sort"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -73,7 +75,8 @@ func (cl *APIClient) DisableDebugMode() *APIClient {

// GetPOSTData method to Serialize given command for POST request
// including connection configuration data
func (cl *APIClient) GetPOSTData(cmd map[string]string) string {
func (cl *APIClient) GetPOSTData(thecmd map[string]interface{}) string {
cmd := cl.flattenCommand(thecmd)
data := cl.socketConfig.GetPOSTData()
var tmp strings.Builder
keys := []string{}
Expand Down Expand Up @@ -199,7 +202,7 @@ func (cl *APIClient) Login(params ...string) *R.Response {
otp = params[0]
}
cl.SetOTP(otp)
rr := cl.Request(map[string]string{"COMMAND": "StartSession"})
rr := cl.Request(map[string]interface{}{"COMMAND": "StartSession"})
if rr.IsSuccess() {
col := rr.GetColumn("SESSION")
if col != nil {
Expand All @@ -224,7 +227,7 @@ func (cl *APIClient) LoginExtended(params ...interface{}) *R.Response {
if len(params) > 0 {
parameters = params[0].(map[string]string)
}
cmd := map[string]string{
cmd := map[string]interface{}{
"COMMAND": "StartSession",
}
for k, v := range parameters {
Expand All @@ -244,7 +247,7 @@ func (cl *APIClient) LoginExtended(params ...interface{}) *R.Response {

// Logout method to perform API logout to close API session in use
func (cl *APIClient) Logout() *R.Response {
rr := cl.Request(map[string]string{
rr := cl.Request(map[string]interface{}{
"COMMAND": "EndSession",
})
if rr.IsSuccess() {
Expand All @@ -254,7 +257,8 @@ func (cl *APIClient) Logout() *R.Response {
}

// Request method to perform API request using the given command
func (cl *APIClient) Request(cmd map[string]string) *R.Response {
func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
newcmd := cl.flattenCommand(cmd)
data := cl.GetPOSTData(cmd)

client := &http.Client{
Expand All @@ -263,9 +267,9 @@ func (cl *APIClient) Request(cmd map[string]string) *R.Response {
req, err := http.NewRequest("POST", cl.socketURL, strings.NewReader(data))
if err != nil {
tpl := rtm.GetTemplate("httperror").GetPlain()
r := R.NewResponse(tpl, cmd)
r := R.NewResponse(tpl, newcmd)
if cl.debugMode {
j, _ := json.Marshal(cmd)
j, _ := json.Marshal(newcmd)
fmt.Printf("%s\n", j)
fmt.Println("POST: " + data)
fmt.Println("HTTP communication failed: " + err.Error())
Expand All @@ -279,9 +283,9 @@ func (cl *APIClient) Request(cmd map[string]string) *R.Response {
resp, err2 := client.Do(req)
if err2 != nil {
tpl := rtm.GetTemplate("httperror").GetPlain()
r := R.NewResponse(tpl, cmd)
r := R.NewResponse(tpl, newcmd)
if cl.debugMode {
j, _ := json.Marshal(cmd)
j, _ := json.Marshal(newcmd)
fmt.Printf("%s\n", j)
fmt.Println("POST: " + data)
fmt.Println("HTTP communication failed: " + err2.Error())
Expand All @@ -294,29 +298,29 @@ func (cl *APIClient) Request(cmd map[string]string) *R.Response {
response, err := ioutil.ReadAll(resp.Body)
if err != nil {
tpl := rtm.GetTemplate("httperror").GetPlain()
r := R.NewResponse(tpl, cmd)
r := R.NewResponse(tpl, newcmd)
if cl.debugMode {
j, _ := json.Marshal(cmd)
j, _ := json.Marshal(newcmd)
fmt.Printf("%s\n", j)
fmt.Println("POST: " + data)
fmt.Println("HTTP communication failed: " + err.Error())
fmt.Println(r.GetPlain())
}
return r
}
r := R.NewResponse(string(response), cmd)
r := R.NewResponse(string(response), newcmd)
if cl.debugMode {
j, _ := json.Marshal(cmd)
j, _ := json.Marshal(newcmd)
fmt.Printf("%s\n", j)
fmt.Println("POST: " + data)
fmt.Println(r.GetPlain())
}
return r
}
tpl := rtm.GetTemplate("httperror").GetPlain()
r := R.NewResponse(tpl, cmd)
r := R.NewResponse(tpl, newcmd)
if cl.debugMode {
j, _ := json.Marshal(cmd)
j, _ := json.Marshal(newcmd)
fmt.Printf("%s\n", j)
fmt.Println("POST: " + data)
fmt.Println(r.GetPlain())
Expand All @@ -327,7 +331,10 @@ func (cl *APIClient) Request(cmd map[string]string) *R.Response {
// RequestNextResponsePage method to request the next page of list entries for the current list query
// Useful for lists
func (cl *APIClient) RequestNextResponsePage(rr *R.Response) (*R.Response, error) {
mycmd := cl.toUpperCaseKeys(rr.GetCommand())
mycmd := map[string]interface{}{}
for key, val := range cl.toUpperCaseKeys(rr.GetCommand()) {
mycmd[key] = val
}
if _, ok := mycmd["LAST"]; ok {
return nil, errors.New("Parameter LAST in use. Please remove it to avoid issues in requestNextPage")
}
Expand All @@ -351,9 +358,8 @@ func (cl *APIClient) RequestNextResponsePage(rr *R.Response) (*R.Response, error
func (cl *APIClient) RequestAllResponsePages(cmd map[string]string) []R.Response {
var err error
responses := []R.Response{}
mycmd := map[string]string{
"FIRST": "0",
}
mycmd := map[string]interface{}{}
mycmd["FIRST"] = "0"
for k, v := range cmd {
mycmd[k] = v
}
Expand Down Expand Up @@ -402,3 +408,24 @@ func (cl *APIClient) toUpperCaseKeys(cmd map[string]string) map[string]string {
}
return newcmd
}

// flattenCommand method to translate all command parameter names to uppercase
func (cl *APIClient) flattenCommand(cmd map[string]interface{}) map[string]string {
newcmd := map[string]string{}
for key, val := range cmd {
if reflect.TypeOf(val).Kind() == reflect.Slice {
v := val.([]string)
for idx, str := range v {
str = strings.Replace(str, "\r", "", -1)
str = strings.Replace(str, "\n", "", -1)
newcmd[key+strconv.Itoa(idx)] = str
}
} else {
val := val.(string)
val = strings.Replace(val, "\r", "", -1)
val = strings.Replace(val, "\n", "", -1)
newcmd[key] = val
}
}
return newcmd
}
Loading

0 comments on commit c11db41

Please sign in to comment.