This repository has been archived by the owner on Jan 11, 2023. It is now read-only.
/
yfws.go
130 lines (109 loc) · 3.29 KB
/
yfws.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package yfws
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/clbanning/mxj"
)
// Make request to Yellowfin service.
func SendRequest(url, msg string, params map[string]string) ([]mxj.Map, error) {
yfrequest, ok := yfRequests[msg]
if !ok {
return nil, fmt.Errorf("invalid request '%s'", msg)
}
local := yfrequest.Request
// Check that all vars are filled
for _, name := range yfrequest.Params {
if value, ok := params[name]; ok {
local = strings.Replace(local, name, value, -1)
} else {
return nil, fmt.Errorf("incomplete request. No value for param '%s'", name)
}
}
req, err := http.NewRequest("POST", url, strings.NewReader(local))
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", "text/xml;charset=UTF-8")
req.Header.Add("SOAPAction", `""`)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
// Read body first to close early, instead of passing to mxj.NewXmlReader.
// Apparently causes less YF errors.
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
resp.Body.Close()
m, err := mxj.NewMapXml(body)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("request error HTTP %d ->\n%s", resp.StatusCode, parseError(m))
}
return parseResponse(m, yfrequest.Call, yfrequest.Resource)
}
// Parse response from Yellowfin service after making request.
func parseResponse(m mxj.Map, responsename, idmapname string) ([]mxj.Map, error) {
path := fmt.Sprintf("Envelope.Body.%sResponse.%sReturn.-href", responsename, responsename)
mainid, err := m.ValueForPathString(path)
if err != nil {
return nil, err
}
value, err := m.ValuesForKey("multiRef", fmt.Sprintf("-id:%s", mainid[1:]))
if err != nil {
return nil, err
}
if len(value) == 0 {
return nil, errors.New("Main reponse not found")
}
valuemap := mxj.Map(value[0].(map[string]interface{}))
statuscode, err := valuemap.ValueForPathString("statusCode.#text")
if err != nil {
return nil, err
}
if statuscode != "SUCCESS" {
errcode, _ := valuemap.ValueForPathString("errorCode.#text")
return nil, YFErrors[errcode]
}
response := make([]mxj.Map, 0, 1)
if idmapname != "" {
ids, err := valuemap.ValuesForPath(idmapname + "." + idmapname)
if err != nil {
return nil, fmt.Errorf("Could not find %s.%s %v", idmapname, idmapname, err)
}
for _, id := range ids {
idmap := mxj.Map(id.(map[string]interface{}))
idvalue, err := idmap.ValueForPathString("-href")
if err != nil {
return nil, err
}
multiref, err := m.ValuesForKey("multiRef", "-id:"+idvalue[1:])
if err != nil {
return nil, fmt.Errorf("Could not find multiref for id %s, %v", idvalue[1:], err)
}
if len(multiref) == 0 {
return nil, fmt.Errorf("mutilRef element not found for id : %s", idvalue[1:])
}
response = append(response, mxj.Map(multiref[0].(map[string]interface{})))
}
} else {
// Add the original back, this is to get responses such as sessionid etc.
response = append(response, valuemap)
}
return response, nil
}
// Parse error response from Yellowfin service after failed request.
func parseError(m mxj.Map) string {
errMsg, err := m.ValueForPathString("Envelope.Body.Fault.faultstring")
if err != nil {
return m.StringIndentNoTypeInfo(0)
}
return errMsg
}