-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
136 lines (118 loc) · 2.42 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
package resty
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/url"
"regexp"
"strings"
)
type Reply struct {
Err error
Status int
Header http.Header
Value []byte
URL string
}
func (r *Reply) Unmarshal(v interface{}) error {
return json.Unmarshal(r.Value, v)
}
type Client struct {
HTTPClient http.Client
BaseURL string
ContentType string
}
func NewClient(baseURL string) *Client {
c := &Client{
BaseURL: baseURL,
ContentType: "application/json",
}
c.Reset()
return c
}
var re = regexp.MustCompile(`/+`)
func (c *Client) GetFullURL(subPath string) (*url.URL, error) {
if strings.HasPrefix(subPath, "http:") || strings.HasPrefix(subPath, "https:") {
return url.Parse(subPath)
}
u, err := url.Parse(c.BaseURL + "/" + subPath)
if u != nil {
u.Path = re.ReplaceAllString(u.Path, "/")
}
return u, err
}
func (c *Client) Do(method, path string, data interface{}, out interface{}) (r Reply) {
var u *url.URL
if u, r.Err = c.GetFullURL(path); r.Err != nil {
return
}
var (
body io.Reader
req *http.Request
)
switch data := data.(type) {
case io.Reader:
body = data
case string:
body = strings.NewReader(data)
case []byte:
body = bytes.NewReader(data)
case nil:
// nothing
default:
if c.ContentType != "application/json" {
panic("not supported")
}
var j []byte
if j, r.Err = json.MarshalIndent(data, "", "\t"); r.Err != nil {
return
}
body = bytes.NewReader(j)
}
if req, r.Err = http.NewRequest(method, u.String(), body); r.Err != nil {
return
}
if body != nil {
req.Header.Set("Content-Type", c.ContentType)
}
var resp *http.Response
if resp, r.Err = c.HTTPClient.Do(req); r.Err != nil {
return
}
defer resp.Body.Close()
r.Status, r.Header = resp.StatusCode, resp.Header
if r.Value, r.Err = ioutil.ReadAll(resp.Body); r.Err != nil {
return
}
if out != nil {
r.Err = r.Unmarshal(out)
}
r.URL = resp.Request.URL.String()
return
}
func (c *Client) RawDo(method, path string) (*http.Response, error) {
var (
u *url.URL
err error
)
if u, err = c.GetFullURL(path); err != nil {
return nil, err
}
var (
req *http.Request
)
if req, err = http.NewRequest(method, u.String(), nil); err != nil {
return nil, err
}
var resp *http.Response
if resp, err = c.HTTPClient.Do(req); err != nil {
return nil, err
}
return resp, nil
}
func (c *Client) Reset() {
c.HTTPClient.Jar, _ = cookiejar.New(nil)
}