forked from ForceCLI/force
/
soap.go
123 lines (113 loc) · 2.72 KB
/
soap.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
package main
import (
"encoding/xml"
"errors"
"fmt"
"io/ioutil"
"strings"
)
type SoapError struct {
FaultCode string `xml:"Body>Fault>faultcode"`
FaultString string `xml:"Body>Fault>faultstring"`
}
type Soap struct {
AccessToken string
Endpoint string
Header string
Namespace string
}
func NewSoap(endpoint, namespace, accessToken string) (s *Soap) {
s = new(Soap)
s.AccessToken = accessToken
s.Namespace = namespace
s.Endpoint = endpoint
return
}
func (s *Soap) ExecuteLogin(username, password string) (response []byte, err error) {
soap := `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:partner.soap.sforce.com">
<soapenv:Body>
<urn:login>
<urn:username>%s</urn:username>
<urn:password>%s</urn:password>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>
`
rbody := fmt.Sprintf(soap, username, password)
req, err := httpRequest("POST", s.Endpoint, strings.NewReader(rbody))
if err != nil {
return
}
req.Header.Add("Content-Type", "text/xml")
req.Header.Add("SOAPACtion", "login")
res, err := httpClient().Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
if res.StatusCode == 401 {
err = errors.New("authorization expired, please run `force login`")
return
}
response, err = ioutil.ReadAll(res.Body)
if err != nil {
return
}
err = processError(response)
return
}
func (s *Soap) Execute(action, query string) (response []byte, err error) {
soap := `
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cmd="%s"
xmlns:apex="http://soap.sforce.com/2006/08/apex">
<env:Header>
<cmd:SessionHeader>
<cmd:sessionId>%s</cmd:sessionId>
</cmd:SessionHeader>
%s
</env:Header>
<env:Body>
<%s xmlns="%s">
%s
</%s>
</env:Body>
</env:Envelope>
`
rbody := fmt.Sprintf(soap, s.Namespace,
s.AccessToken, s.Header, action, s.Namespace, query, action)
req, err := httpRequest("POST", s.Endpoint, strings.NewReader(rbody))
if err != nil {
return
}
req.Header.Add("Content-Type", "text/xml")
req.Header.Add("SOAPACtion", action)
res, err := httpClient().Do(req)
if err != nil {
return
}
defer res.Body.Close()
if res.StatusCode == 401 {
err = errors.New("authorization expired, please run `force login`")
return
}
response, err = ioutil.ReadAll(res.Body)
if err != nil {
return
}
err = processError(response)
return
}
func processError(body []byte) (err error) {
var soapError SoapError
xml.Unmarshal(body, &soapError)
if soapError.FaultCode != "" {
return errors.New(soapError.FaultString)
}
return
}