Skip to content

Commit 87df76b

Browse files
feat(response): possibility of placeholder vars in standard responses to improve error details
1 parent 3f4caa6 commit 87df76b

File tree

6 files changed

+63
-20
lines changed

6 files changed

+63
-20
lines changed

apiclient/apiclient.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
324324
newcmd = cl.autoIDNConvert(newcmd)
325325

326326
// request command to API
327+
cfg := map[string]string{
328+
"CONNECTION_URL": cl.socketURL,
329+
}
327330
data := cl.GetPOSTData(newcmd, false)
328331
secured := cl.GetPOSTData(newcmd, true)
329332

@@ -339,10 +342,10 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
339342
fmt.Println("Not able to parse configured Proxy URL: " + val)
340343
}
341344
}
342-
req, err := http.NewRequest("POST", cl.socketURL, strings.NewReader(data))
345+
req, err := http.NewRequest("POST", cfg["CONNECTION_URL"], strings.NewReader(data))
343346
if err != nil {
344347
tpl := rtm.GetTemplate("httperror").GetPlain()
345-
r := R.NewResponse(tpl, newcmd)
348+
r := R.NewResponse(tpl, newcmd, cfg)
346349
if cl.debugMode {
347350
j, _ := json.Marshal(newcmd)
348351
fmt.Printf("%s\n", j)
@@ -362,7 +365,7 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
362365
resp, err2 := client.Do(req)
363366
if err2 != nil {
364367
tpl := rtm.GetTemplate("httperror").GetPlain()
365-
r := R.NewResponse(tpl, newcmd)
368+
r := R.NewResponse(tpl, newcmd, cfg)
366369
if cl.debugMode {
367370
j, _ := json.Marshal(newcmd)
368371
fmt.Printf("%s\n", j)
@@ -377,7 +380,7 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
377380
response, err := ioutil.ReadAll(resp.Body)
378381
if err != nil {
379382
tpl := rtm.GetTemplate("httperror").GetPlain()
380-
r := R.NewResponse(tpl, newcmd)
383+
r := R.NewResponse(tpl, newcmd, cfg)
381384
if cl.debugMode {
382385
j, _ := json.Marshal(newcmd)
383386
fmt.Printf("%s\n", j)
@@ -387,7 +390,7 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
387390
}
388391
return r
389392
}
390-
r := R.NewResponse(string(response), newcmd)
393+
r := R.NewResponse(string(response), newcmd, cfg)
391394
if cl.debugMode {
392395
j, _ := json.Marshal(newcmd)
393396
fmt.Printf("%s\n", j)
@@ -397,7 +400,7 @@ func (cl *APIClient) Request(cmd map[string]interface{}) *R.Response {
397400
return r
398401
}
399402
tpl := rtm.GetTemplate("httperror").GetPlain()
400-
r := R.NewResponse(tpl, newcmd)
403+
r := R.NewResponse(tpl, newcmd, cfg)
401404
if cl.debugMode {
402405
j, _ := json.Marshal(newcmd)
403406
fmt.Printf("%s\n", j)

response/response.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ package response
99
import (
1010
"errors"
1111
"math"
12+
"regexp"
13+
"sort"
1214
"strconv"
1315
"strings"
1416

@@ -29,7 +31,7 @@ type Response struct {
2931
}
3032

3133
// NewResponse represents the constructor for struct Response.
32-
func NewResponse(raw string, cmd map[string]string) *Response {
34+
func NewResponse(raw string, cmd map[string]string, ph ...map[string]string) *Response {
3335
r := &Response{
3436
command: cmd,
3537
columnkeys: []string{},
@@ -43,6 +45,21 @@ func NewResponse(raw string, cmd map[string]string) *Response {
4345
}
4446
r.ResponseTemplate = rt.NewResponseTemplate(raw)
4547

48+
// care about getting placeholder variables replaced
49+
re := regexp.MustCompile(`\{[A-Z_]+\}`)
50+
if re.MatchString(r.ResponseTemplate.Raw) {
51+
phs := map[string]string{}
52+
if len(ph) > 0 {
53+
phs = ph[0]
54+
}
55+
newraw := r.ResponseTemplate.Raw
56+
for key, val := range phs {
57+
newraw = strings.ReplaceAll(newraw, "{"+key+"}", val)
58+
}
59+
newraw = re.ReplaceAllString(newraw, "")
60+
r.ResponseTemplate = rt.NewResponseTemplate(newraw)
61+
}
62+
4663
h := r.ResponseTemplate.GetHash()
4764
if p, ok := h["PROPERTY"]; ok {
4865
prop := p.(map[string][]string)
@@ -129,11 +146,17 @@ func (r *Response) GetCommand() map[string]string {
129146

130147
// GetCommandPlain method to get the underlying API command in plain text
131148
func (r *Response) GetCommandPlain() string {
149+
keys := make([]string, 0, len(r.command))
150+
for k := range r.command {
151+
keys = append(keys, k)
152+
}
153+
sort.Strings(keys)
154+
132155
var strBuilder strings.Builder
133-
for key, val := range r.command {
134-
strBuilder.WriteString(key)
156+
for i := 0; i < len(keys); i++ {
157+
strBuilder.WriteString(keys[i])
135158
strBuilder.WriteString(" = ")
136-
strBuilder.WriteString(val)
159+
strBuilder.WriteString(r.command[keys[i]])
137160
strBuilder.WriteString("\n")
138161
}
139162
return strBuilder.String()

response/response_test.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"reflect"
7+
"regexp"
78
"strings"
89
"testing"
910

@@ -29,15 +30,31 @@ func TestMain(m *testing.M) {
2930
os.Exit(m.Run())
3031
}
3132

33+
func TestPlaceHolderReplacements(t *testing.T) {
34+
r := NewResponse("", map[string]string{
35+
"COMMAND": "StatusAccount",
36+
})
37+
re := regexp.MustCompile(`\{[A-Z_]+\}`)
38+
if re.MatchString(r.GetDescription()) {
39+
t.Error("TestPlaceHolderReplacements: place holders not removed.")
40+
}
41+
42+
r = NewResponse("", map[string]string{"COMMAND": "StatusAccount"}, map[string]string{"CONNECTION_URL": "123HXPHFOUND123"})
43+
re = regexp.MustCompile(`123HXPHFOUND123`)
44+
if !re.MatchString(r.GetDescription()) {
45+
t.Error("TestPlaceHolderReplacements: CONNECTION_URL place holder not removed.\n" + r.GetDescription())
46+
}
47+
}
48+
3249
func TestGetCommandPlain(t *testing.T) {
3350
r := NewResponse("", map[string]string{
3451
"COMMAND": "QueryDomainOptions",
3552
"DOMAIN0": "example.com",
3653
"DOMAIN1": "example.net",
3754
})
3855
expected := "COMMAND = QueryDomainOptions\nDOMAIN0 = example.com\nDOMAIN1 = example.net\n"
39-
if r.GetCommandPlain() != expected {
40-
t.Error("TestGetCommandPlain: plain text command not matching expected value.")
56+
if strings.Compare(r.GetCommandPlain(), expected) != 0 {
57+
t.Error("TestGetCommandPlain: plain text command not matching expected value.\n\n" + r.GetCommandPlain())
4158
}
4259
}
4360

@@ -47,9 +64,9 @@ func TestGetCommandPlainSecure(t *testing.T) {
4764
"SUBUSER": "test.user",
4865
"PASSWORD": "test.passw0rd",
4966
})
50-
expected := "COMMAND = CheckAuthentication\nSUBUSER = test.user\nPASSWORD = ***\n"
51-
if r.GetCommandPlain() != expected {
52-
t.Error("TestGetCommandPlainSecure: plain text command not matching expected value.")
67+
expected := "COMMAND = CheckAuthentication\nPASSWORD = ***\nSUBUSER = test.user\n"
68+
if strings.Compare(r.GetCommandPlain(), expected) != 0 {
69+
t.Error("TestGetCommandPlainSecure: plain text command not matching expected value.\n\n" + r.GetCommandPlain() + "\n\n" + expected)
5370
}
5471
}
5572

responsetemplate/responsetemplate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type ResponseTemplate struct {
2222
// NewResponseTemplate represents the constructor for struct ResponseTemplate.
2323
func NewResponseTemplate(raw string) *ResponseTemplate {
2424
if len(raw) == 0 {
25-
raw = "[RESPONSE]\r\nCODE=423\r\nDESCRIPTION=Empty API response. Probably unreachable API end point\r\nEOF\r\n"
25+
raw = "[RESPONSE]\r\nCODE=423\r\nDESCRIPTION=Empty API response. Probably unreachable API end point {CONNECTION_URL}\r\nEOF\r\n"
2626
}
2727
rt := &ResponseTemplate{
2828
Raw: raw,

responsetemplate/responsetemplate_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ func TestConstructor(t *testing.T) {
1010
if tpl.GetCode() != 423 {
1111
t.Error("TestConstructor: Expected response code not matching.")
1212
}
13-
if strings.Compare(tpl.GetDescription(), "Empty API response. Probably unreachable API end point") != 0 {
14-
t.Error("TestConstructor: Expected response description not matching.")
13+
if strings.Compare(tpl.GetDescription(), "Empty API response. Probably unreachable API end point {CONNECTION_URL}") != 0 {
14+
t.Error("TestConstructor: Expected response description not matching.\n\n" + tpl.GetDescription())
1515
}
1616

1717
tpl = NewResponseTemplate("[RESPONSE]\r\ncode=200\r\nqueuetime=0\r\nEOF\r\n")
@@ -28,7 +28,7 @@ func TestGetHash(t *testing.T) {
2828
if v, ok := h["CODE"]; !ok || strings.Compare(v.(string), "423") != 0 {
2929
t.Error("TestGetHash: Expected response code not matching.")
3030
}
31-
if v, ok := h["DESCRIPTION"]; !ok || strings.Compare(v.(string), "Empty API response. Probably unreachable API end point") != 0 {
31+
if v, ok := h["DESCRIPTION"]; !ok || strings.Compare(v.(string), "Empty API response. Probably unreachable API end point {CONNECTION_URL}") != 0 {
3232
t.Error("TestGetHash: Expected response description not matching.")
3333
}
3434
}

responsetemplatemanager/responsetemplatemanager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func GetInstance() *ResponseTemplateManager {
3030
templates: map[string]string{
3131
"404": generateTemplate("421", "Page not found"),
3232
"500": generateTemplate("500", "Internal server error"),
33-
"empty": generateTemplate("423", "Empty API response. Probably unreachable API end point"),
33+
"empty": generateTemplate("423", "Empty API response. Probably unreachable API end point {CONNECTION_URL}"),
3434
"error": generateTemplate("421", "Command failed due to server error. Client should try again"),
3535
"expired": generateTemplate("530", "SESSION NOT FOUND"),
3636
"httperror": generateTemplate("421", "Command failed due to HTTP communication error"),

0 commit comments

Comments
 (0)