/
client.go
141 lines (112 loc) · 3.62 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
package sdk
import (
"fmt"
"net/http"
"runtime"
"strings"
"github.com/marmotedu/component-base/pkg/json"
"github.com/marmotedu/medu-sdk-go/sdk/log"
"github.com/marmotedu/medu-sdk-go/sdk/request"
"github.com/marmotedu/medu-sdk-go/sdk/response"
)
var defaultUserAgent = fmt.Sprintf("MEDUSDKGo/%s (%s; %s) Golang/%s", Version, runtime.GOOS, runtime.GOARCH, strings.Trim(runtime.Version(), "go"))
// Client is the base struct of service clients
type Client struct {
signMethod string
Credential *Credential
Config *Config
ServiceName string
Logger log.Logger
}
type SignFunc func(*http.Request) error
// ListOptions specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
Offset *int64 `json:"offset,omitempty"`
Limit *int64 `json:"limit,omitempty"`
}
func (c *Client) Init(serviceName string) *Client {
c.signMethod = "jwt"
c.Logger = log.New()
c.ServiceName = serviceName
return c
}
func (c *Client) WithCredential(cred *Credential) *Client {
c.Credential = cred
return c
}
func (c *Client) WithSecret(secretID, secretKey string) *Client {
c.Credential = NewCredentials(secretID, secretKey)
return c
}
func (c *Client) WithConfig(config *Config) *Client {
c.Config = config
c.Logger.SetLevel(config.LogLevel)
return c
}
// Send send the request and return the response to the client.
// Parameter request accepts concrete request object which follow Request.
func (c *Client) Send(req request.Request, resp response.Response) error {
method := req.GetMethod()
builder := GetParameterBuilder(method, c.Logger)
jsonReq, _ := json.Marshal(req)
encodedUrl, err := builder.BuildURL(req.GetURL(), jsonReq)
if err != nil {
return err
}
endPoint := c.Config.Endpoint
if endPoint == "" {
endPoint = fmt.Sprintf("%s/%s", defaultEndpoint, c.ServiceName)
}
reqUrl := fmt.Sprintf("%s://%s/%s%s", c.Config.Scheme, endPoint, req.GetVersion(), encodedUrl)
body, err := builder.BuildBody(jsonReq)
if err != nil {
return err
}
sign := func(r *http.Request) error {
signer := NewSigner(c.signMethod, c.Credential, c.Logger)
_ = signer.Sign(c.ServiceName, r, strings.NewReader(body))
return err
}
rawResponse, err := c.doSend(method, reqUrl, body, req.GetHeaders(), sign)
if err != nil {
return err
}
return response.ParseFromHttpResponse(rawResponse, resp)
}
func (c *Client) doSend(method, url, data string, header map[string]string, sign SignFunc) (*http.Response, error) {
client := &http.Client{Timeout: c.Config.Timeout}
req, err := http.NewRequest(method, url, strings.NewReader(data))
if err != nil {
c.Logger.Errorf("%s", err.Error())
return nil, err
}
c.setHeader(req, header)
err = sign(req)
if err != nil {
return nil, err
}
return client.Do(req)
}
func (c *Client) setHeader(req *http.Request, header map[string]string) {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", defaultUserAgent)
for k, v := range header {
req.Header.Set(k, v)
}
for k, v := range req.Header {
c.Logger.Infof("header key: %s, header value: %s", k, v)
}
}
// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
func Bool(v bool) *bool { return &v }
// Int is a helper routine that allocates a new int value
// to store v and returns a pointer to it.
func Int(v int) *int { return &v }
// Int64 is a helper routine that allocates a new int64 value
// to store v and returns a pointer to it.
func Int64(v int64) *int64 { return &v }
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string { return &v }