Skip to content

Commit b1095d1

Browse files
committed
optimize http get/post
1 parent bb4e013 commit b1095d1

15 files changed

+227
-546
lines changed

custom.go

+8-37
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package weixin
33
import (
44
"encoding/json"
55
"fmt"
6-
"io/ioutil"
7-
"net/http"
86
"os"
97
)
108

@@ -64,26 +62,19 @@ func DeleteCustomStruct(cust *Custom) (err error) {
6462

6563
// operateCustomStruct 客服帐号
6664
func operateCustomStruct(url string, cust *Custom) (err error) {
67-
jsonBytes, err := json.Marshal(cust)
68-
if err != nil {
69-
return err
70-
}
71-
72-
err = Post(url, jsonBytes)
73-
return err
65+
return Post(url, cust, nil)
7466
}
7567

7668
// UploadHeading 设置客服帐号的头像
7769
func UploadHeading(account string, file *os.File) (err error) {
7870
url := fmt.Sprintf(CustomHeadingURL, AccessToken(), account)
79-
wxerr := &WeixinError{} // 忽略返回
80-
return Upload(url, file.Name(), file, wxerr)
71+
return Upload(url, file.Name(), file, nil)
8172
}
8273

8374
// CustomList 客服列表
8475
type CustomList struct {
85-
WeixinError
86-
List []Account `json:"kf_list"`
76+
WXError
77+
List []*Account `json:"kf_list"`
8778
}
8879

8980
// Account 客服账号
@@ -95,29 +86,11 @@ type Account struct {
9586
}
9687

9788
// GetCustomList 获取所有客服账号
98-
func GetCustomList() (accs []Account, err error) {
89+
func GetCustomList() (accs []*Account, err error) {
9990
url := fmt.Sprintf(CustomListURL, AccessToken())
100-
resp, err := http.Get(url)
101-
if err != nil {
102-
return nil, err
103-
}
104-
105-
body, err := ioutil.ReadAll(resp.Body)
106-
if err != nil {
107-
return nil, err
108-
}
109-
11091
list := &CustomList{}
111-
err = json.Unmarshal(body, list)
112-
if err != nil {
113-
return nil, err
114-
}
115-
116-
if list.ErrCode != WeixinErrCodeSuccess {
117-
return nil, list
118-
}
119-
120-
return list.List, nil
92+
err = Get(url, list)
93+
return list.List, err
12194
}
12295

12396
// CustMsg 客服消息接口
@@ -199,7 +172,5 @@ func SendCustomMsg(openId string, msg CustMsg) (err error) {
199172
openId, msgType, msgType, js)
200173

201174
url := fmt.Sprintf(CustomMsgURL, AccessToken())
202-
err = Post(url, []byte(jsonStr))
203-
204-
return err
175+
return Post(url, []byte(jsonStr), nil)
205176
}

errors.go

-173
This file was deleted.

http.go

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package weixin
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"io/ioutil"
10+
"mime"
11+
"mime/multipart"
12+
"net/http"
13+
"os"
14+
15+
"github.com/arstd/log"
16+
)
17+
18+
type wxResp interface {
19+
// 似有的 error 方法,保证外部(其他包)定义的 struct 只能内嵌
20+
// WXError 的才能实现这个方法,才能作为当前包 http 方法的参数
21+
error() error
22+
}
23+
24+
type WXError struct {
25+
ErrCode int `json:"errcode,omitempty"`
26+
Errmsg string `json:"errmsg,omitempty"`
27+
}
28+
29+
func (e *WXError) error() error {
30+
if e.ErrCode == 0 {
31+
return nil
32+
}
33+
return e
34+
}
35+
36+
func (e *WXError) Error() string {
37+
return fmt.Sprintf("weixin: (%d)%s", e.ErrCode, e.Errmsg)
38+
}
39+
40+
var client = http.Client{
41+
Transport: &http.Transport{
42+
MaxIdleConnsPerHost: 128,
43+
},
44+
}
45+
46+
// GetUnmarshal HTTP 工具类, GET 并解析返回的报文,如果有错误,返回 error
47+
func Get(url string, wxr wxResp) error {
48+
resp, err := client.Get(url)
49+
if err != nil {
50+
return err
51+
}
52+
53+
return parseWXResp(resp, wxr)
54+
}
55+
56+
const contentType = "application/json"
57+
58+
// Post HTTP 工具类, POST 并解析返回的报文,如果有错误,返回 error
59+
func Post(url string, v interface{}, wxr wxResp) (err error) {
60+
var js []byte
61+
if _, ok := v.([]byte); !ok {
62+
js, err = json.Marshal(v)
63+
if err != nil {
64+
return err
65+
}
66+
}
67+
68+
resp, err := client.Post(url, contentType, bytes.NewBuffer(js))
69+
if err != nil {
70+
return err
71+
}
72+
return parseWXResp(resp, wxr)
73+
}
74+
75+
// Upload 工具类, 上传文件
76+
func Upload(url, fieldName string, file *os.File, wxr wxResp, desc ...string) (err error) {
77+
buf := &bytes.Buffer{}
78+
w := multipart.NewWriter(buf)
79+
80+
//关键的一步操作
81+
// fw, err := w.CreateFormField(file.Name())
82+
fw, err := w.CreateFormFile(fieldName, file.Name())
83+
if err != nil {
84+
return err
85+
}
86+
_, err = io.Copy(fw, file)
87+
if err != nil {
88+
return err
89+
}
90+
contentType := w.FormDataContentType()
91+
if len(desc) > 0 {
92+
w.WriteField("description", desc[0])
93+
}
94+
w.Close()
95+
96+
log.Debugf("url=%s, fieldName=%s, fileName=%s", url, fieldName, file.Name())
97+
resp, err := client.Post(url, contentType, buf)
98+
if err != nil {
99+
return err
100+
}
101+
102+
return parseWXResp(resp, wxr)
103+
}
104+
105+
func Download(url string) (filename string, body []byte, err error) {
106+
resp, err := client.Get(url)
107+
if err != nil {
108+
return "", nil, err
109+
}
110+
111+
var params map[string]string
112+
if cd := resp.Header.Get("Content-Disposition"); cd == "" {
113+
return "", nil, errors.New("missing Content-Disposition header")
114+
} else if _, params, err = mime.ParseMediaType(cd); err != nil {
115+
return "", nil, err
116+
} else if filename = params["filename"]; filename == "" {
117+
return "", nil, errors.New("no filename in Content-Disposition header")
118+
}
119+
120+
body, err = ioutil.ReadAll(resp.Body)
121+
resp.Body.Close()
122+
return filename, body, err
123+
}
124+
125+
func parseWXResp(resp *http.Response, wxr wxResp) error {
126+
js, err := ioutil.ReadAll(resp.Body)
127+
resp.Body.Close()
128+
if err != nil {
129+
return err
130+
}
131+
132+
log.Trace("%s", js)
133+
if wxr == nil {
134+
wxr = &WXError{}
135+
}
136+
err = json.Unmarshal(js, wxr)
137+
if err != nil {
138+
return err
139+
}
140+
141+
return wxr.error()
142+
}

0 commit comments

Comments
 (0)