-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathrequests.go
125 lines (111 loc) · 2.92 KB
/
requests.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
package salesforce
import (
"bytes"
"compress/gzip"
"encoding/json"
"errors"
"io"
"net/http"
"strings"
)
type requestPayload struct {
method string
uri string
content string
body string
retry bool
compress bool
}
func doRequest(auth *authentication, payload requestPayload) (*http.Response, error) {
var reader io.Reader
var req *http.Request
var err error
endpoint := auth.InstanceUrl + "/services/data/" + apiVersion + payload.uri
if payload.body != "" {
if payload.compress {
reader, err = compress(payload.body)
if err != nil {
return nil, err
}
} else {
reader = strings.NewReader(payload.body)
}
req, err = http.NewRequest(payload.method, endpoint, reader)
} else {
req, err = http.NewRequest(payload.method, endpoint, nil)
}
if err != nil {
return nil, err
}
req.Header.Set("User-Agent", "go-salesforce")
req.Header.Set("Content-Type", payload.content)
req.Header.Set("Accept", payload.content)
req.Header.Set("Authorization", "Bearer "+auth.AccessToken)
if payload.compress {
req.Header.Set("Content-Encoding", "gzip") // compress request
req.Header.Set("Accept-Encoding", "gzip") // compress response
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return resp, err
}
if resp.StatusCode < 200 || resp.StatusCode > 300 {
resp, err = processSalesforceError(*resp, auth, payload)
if err != nil {
return resp, err
}
}
// salesforce does not guarantee that the response will be compressed
if resp.Header.Get("Content-Encoding") == "gzip" {
resp.Body, err = decompress(resp.Body)
}
return resp, err
}
func compress(body string) (io.Reader, error) {
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
if _, err := gz.Write([]byte(body)); err != nil {
return nil, err
}
if err := gz.Close(); err != nil {
return nil, err
}
return &buf, nil
}
func decompress(body io.ReadCloser) (io.ReadCloser, error) {
gzReader, err := gzip.NewReader(body)
if err != nil {
return nil, err
}
defer gzReader.Close()
decompressed, err := io.ReadAll(gzReader)
if err != nil {
return nil, err
}
return io.NopCloser(bytes.NewReader(decompressed)), nil
}
func processSalesforceError(resp http.Response, auth *authentication, payload requestPayload) (*http.Response, error) {
responseData, err := io.ReadAll(resp.Body)
if err != nil {
return &resp, err
}
var sfErrors []SalesforceErrorMessage
err = json.Unmarshal(responseData, &sfErrors)
if err != nil {
return &resp, err
}
for _, sfError := range sfErrors {
if sfError.ErrorCode == invalidSessionIdError && !payload.retry { // only attempt to refresh the session once
err = refreshSession(auth)
if err != nil {
return &resp, err
}
newResp, err := doRequest(auth, requestPayload{payload.method, payload.uri, payload.content, payload.body, true, payload.compress})
if err != nil {
return &resp, err
}
return newResp, nil
}
}
return &resp, errors.New(string(responseData))
}