84 lines
2.0 KiB
Go
84 lines
2.0 KiB
Go
package mes
|
||||
|
|
|
|||
|
|
import (
|
|||
|
|
"bytes"
|
|||
|
|
"encoding/json"
|
|||
|
|
"fmt"
|
|||
|
|
"io"
|
|||
|
|
"net/http"
|
|||
|
|
"net/url"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// Client MES 内部 API HTTP 客户端。
|
|||
|
|
// 自动携带请求头:X-API-TOKEN(项目间 token)、Content-Type: application/json。
|
|||
|
|
// 任何非 2xx 状态返回包含响应体的错误信息。
|
|||
|
|
type Client struct {
|
|||
|
|
baseURL string
|
|||
|
|
token string
|
|||
|
|
httpClient *http.Client
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func New(baseURL, token string) *Client {
|
|||
|
|
return &Client{
|
|||
|
|
baseURL: strings.TrimRight(baseURL, "/"),
|
|||
|
|
token: token,
|
|||
|
|
httpClient: &http.Client{Timeout: 10 * time.Second},
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Get 发送 GET 请求,query 为空则忽略。
|
|||
|
|
func (c *Client) Get(path string, query url.Values) ([]byte, http.Header, error) {
|
|||
|
|
u := c.baseURL + path
|
|||
|
|
if len(query) > 0 {
|
|||
|
|
u += "?" + query.Encode()
|
|||
|
|
}
|
|||
|
|
return c.do(http.MethodGet, u, nil)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Post 发送 POST 请求,body 序列化为 JSON(body 为 nil 则不发送请求体)。
|
|||
|
|
func (c *Client) Post(path string, body any) ([]byte, http.Header, error) {
|
|||
|
|
var reader io.Reader
|
|||
|
|
if body != nil {
|
|||
|
|
b, err := json.Marshal(body)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, fmt.Errorf("序列化请求体失败: %w", err)
|
|||
|
|
}
|
|||
|
|
reader = bytes.NewReader(b)
|
|||
|
|
}
|
|||
|
|
return c.do(http.MethodPost, c.baseURL+path, reader)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (c *Client) do(method, u string, body io.Reader) ([]byte, http.Header, error) {
|
|||
|
|
req, err := http.NewRequest(method, u, body)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
req.Header.Set("X-API-TOKEN", c.token)
|
|||
|
|
req.Header.Set("Content-Type", "application/json;charset=utf-8")
|
|||
|
|
|
|||
|
|
resp, err := c.httpClient.Do(req)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, nil, err
|
|||
|
|
}
|
|||
|
|
defer resp.Body.Close()
|
|||
|
|
|
|||
|
|
respBody, err := io.ReadAll(resp.Body)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, resp.Header, err
|
|||
|
|
}
|
|||
|
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
|||
|
|
return respBody, resp.Header, fmt.Errorf("MES %s %s 返回 %d:%s",
|
|||
|
|
method, u, resp.StatusCode, truncate(string(respBody), 200))
|
|||
|
|
}
|
|||
|
|
return respBody, resp.Header, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func truncate(s string, n int) string {
|
|||
|
|
s = strings.TrimSpace(s)
|
|||
|
|
if len(s) > n {
|
|||
|
|
return s[:n] + "..."
|
|||
|
|
}
|
|||
|
|
return s
|
|||
|
|
}
|