-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
157 lines (128 loc) · 4.46 KB
/
client.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package jrpc2client
import (
"encoding/base64"
"os"
"sync"
"time"
"github.com/sirupsen/logrus"
"github.com/valyala/fasthttp"
)
func getDefaultHeadersMap() map[string]string {
headers := make(map[string]string)
headers["User-Agent"] = userAgent
headers["Content-Type"] = defaultContentType
return headers
}
func createNewClient(logger *logrus.Logger) *Client {
return &Client{
clientPool: &sync.Pool{
New: func() interface{} {
return new(fasthttp.Client)
},
},
customHeaders: getDefaultHeadersMap(),
logger: logger,
}
}
// NewClient returns new configured Client to start work with JSON-RPC 2.0 protocol
func NewClient() *Client {
return createNewClient(&logrus.Logger{Out: os.Stdout, Formatter: &logrus.JSONFormatter{DisableTimestamp: false}, Level: logrus.WarnLevel})
}
// NewClientWithLogger returns new configured Client with custom Logger configureation (based on Sirupsen/logrus) to start work with JSON-RPC 2.0 protocol
func NewClientWithLogger(logger *logrus.Logger) *Client {
return createNewClient(logger)
}
// SetBaseURL setting basic url for API
func (cl *Client) SetBaseURL(baseURL string) {
cl.BaseURL = baseURL
}
// DisableHeaderNamesNormalizing setting normalize headers or not
func (cl *Client) DisableHeaderNamesNormalizing(fix bool) {
cl.disableHeaderNamesNormalizing = fix
}
// SetClientTimeout this method sets globally for client its timeout
func (cl *Client) SetClientTimeout(duration time.Duration) {
cl.clientTimeout = duration
}
// SetCustomHeader setting custom header
func (cl *Client) SetCustomHeader(headerName string, headerValue string) {
cl.customHeaders[headerName] = headerValue
}
// DeleteCustomHeader delete custom header
func (cl *Client) DeleteCustomHeader(headerName string) {
delete(cl.customHeaders, headerName)
}
// SetBasicAuthHeader setting basic auth header
func (cl *Client) SetBasicAuthHeader(login string, password string) {
cl.SetCustomAuthHeader("Basic", base64.StdEncoding.EncodeToString([]byte(login+":"+password)))
}
// SetCustomAuthHeader setting custom auth header with type of auth and auth data
func (cl *Client) SetCustomAuthHeader(authType string, authData string) {
cl.SetCustomHeader("Authorization", authType+" "+authData)
}
// DeleteAuthHeader clear basic auth header
func (cl *Client) DeleteAuthHeader() {
cl.DeleteCustomHeader("Authorization")
}
// SetUserAgent setting custom User Agent header
func (cl *Client) SetUserAgent(userAgent string) {
cl.SetCustomHeader("User-Agent", userAgent)
}
func (cl *Client) makeCallRequest(urlPath string, method string, args interface{}) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer req.Reset()
req.SetRequestURI(cl.BaseURL + urlPath)
for key, val := range cl.customHeaders {
req.Header.Set(key, val)
}
req.Header.SetMethod("POST")
byteBody, err := encodeClientRequest(method, args)
if err != nil {
return nil, err
}
debugLogging(cl, logrus.Fields{"headers": req.Header.String(), "request": byteBody}, "request prepared")
req.SetBody(byteBody)
resp := fasthttp.AcquireResponse()
defer resp.Reset()
client := cl.clientPool.Get().(*fasthttp.Client)
client.DisableHeaderNamesNormalizing = cl.disableHeaderNamesNormalizing
if cl.clientTimeout == 0 {
if err := client.Do(req, resp); err != nil {
return nil, err
}
} else {
if err := client.DoTimeout(req, resp, cl.clientTimeout); err != nil {
return nil, err
}
}
cl.clientPool.Put(client)
debugLogging(cl, logrus.Fields{"headers": req.Header.String(), "response": resp.Body()}, "response received")
return resp.Body(), nil
}
// Call run remote procedure on JSON-RPC 2.0 API with parsing answer to provided structure or interface
func (cl *Client) Call(urlPath string, method string, args interface{}, dst interface{}) error {
resp, err := cl.makeCallRequest(urlPath, method, args)
if err != nil {
return err
}
err = decodeClientResponse(resp, &dst)
return err
}
// CallForMap run remote procedure on JSON-RPC 2.0 API with returning map[string]interface{}
func (cl *Client) CallForMap(urlPath string, method string, args interface{}) (map[string]interface{}, error) {
resp, err := cl.makeCallRequest(urlPath, method, args)
if err != nil {
return nil, err
}
dst := make(map[string]interface{})
err = decodeClientResponse(resp, &dst)
return dst, err
}
/*
func (cl *Client) CallBatch(urlPath string, method string, args interface{}) {
}
func (cl *Client) AsyncCall(urlPath string, method string, args interface{}, ch chan<- interface{}) {
var result interface{}
ch <- result
}
*/