docs(README): 更新文档为中文并完善API参考
- 将README从英文翻译为中文 - 添加详细的API参考文档,包括所有管理接口和枚举值说明 - 补充安装、快速开始、认证方式等使用指南 refactor(client): 优化客户端代码结构并添加详细注释 - 为所有API方法添加中文注释和使用说明 - 改进Client结构体和Option配置的设计 - 统一错误处理和响应结构的文档说明
This commit is contained in:
@@ -12,25 +12,45 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Client 是访问 Email Server 后端的 HTTP 客户端。
|
||||
// 同一个 Client 可以同时持有 ServiceToken 与 AppKey/Secret,
|
||||
// 两种头会同时带上;一般建议按用途分别创建实例。
|
||||
//
|
||||
// 构造方式:
|
||||
// - NewServiceClient: 管理端(Authorization: Bearer <token>)
|
||||
// - NewAppClient: 发件端 (X-App-Key / X-App-Secret)
|
||||
type Client struct {
|
||||
baseURL string
|
||||
serviceToken string
|
||||
appKey string
|
||||
appSecret string
|
||||
httpClient *http.Client
|
||||
baseURL string // 基础地址,不带尾斜杠,例如 https://api.example.com
|
||||
serviceToken string // ServiceAuth 令牌(管理接口)
|
||||
appKey string // AppAuth AppKey(发件接口)
|
||||
appSecret string // AppAuth AppSecret
|
||||
httpClient *http.Client // 底层 HTTP 客户端,默认超时 30s
|
||||
}
|
||||
|
||||
// Option 用于在构造 Client 时传入可选配置。
|
||||
type Option func(*Client)
|
||||
|
||||
// WithHTTPClient 使用自定义 *http.Client,例如配置代理、传输层、证书等。
|
||||
func WithHTTPClient(hc *http.Client) Option {
|
||||
return func(c *Client) { c.httpClient = hc }
|
||||
}
|
||||
|
||||
// WithTimeout 修改底层 HTTP 客户端的超时(默认 30 秒)。
|
||||
//
|
||||
// 注意:如果同时使用 WithHTTPClient,请确保先设置自定义客户端再应用超时。
|
||||
func WithTimeout(d time.Duration) Option {
|
||||
return func(c *Client) { c.httpClient.Timeout = d }
|
||||
}
|
||||
|
||||
// NewServiceClient creates a client authenticated with a service token (management APIs).
|
||||
// NewServiceClient 创建一个管理端客户端。
|
||||
//
|
||||
// 参数:
|
||||
// - baseURL: 后端根地址,例如 "https://mail.example.com"
|
||||
// - serviceToken: 后端环境变量 SERVICE_TOKEN 的值
|
||||
// - opts: 可选项(WithHTTPClient / WithTimeout)
|
||||
//
|
||||
// 所有请求会自动带上 Authorization: Bearer <serviceToken> 头,
|
||||
// 覆盖账号、签名、配额、通道、发信、审核、队列、健康检查等全部管理接口。
|
||||
func NewServiceClient(baseURL, serviceToken string, opts ...Option) *Client {
|
||||
c := &Client{
|
||||
baseURL: strings.TrimRight(baseURL, "/"),
|
||||
@@ -43,7 +63,14 @@ func NewServiceClient(baseURL, serviceToken string, opts ...Option) *Client {
|
||||
return c
|
||||
}
|
||||
|
||||
// NewAppClient creates a client authenticated with AppKey/AppSecret (mail sending API).
|
||||
// NewAppClient 创建一个发件客户端。
|
||||
//
|
||||
// 参数:
|
||||
// - baseURL: 后端根地址
|
||||
// - appKey / appSecret: 管理端创建账号时返回的凭据
|
||||
// - opts: 可选项(WithHTTPClient / WithTimeout)
|
||||
//
|
||||
// 只能用于调用 SendMail 接口。若要调用管理接口,请改用 NewServiceClient。
|
||||
func NewAppClient(baseURL, appKey, appSecret string, opts ...Option) *Client {
|
||||
c := &Client{
|
||||
baseURL: strings.TrimRight(baseURL, "/"),
|
||||
@@ -57,25 +84,39 @@ func NewAppClient(baseURL, appKey, appSecret string, opts ...Option) *Client {
|
||||
return c
|
||||
}
|
||||
|
||||
// APIResponse 是后端统一响应体。
|
||||
//
|
||||
// { "code": 200, "message": "ok", "data": ... }
|
||||
//
|
||||
// SDK 内部会解包 Data,正常情况下调用方无需直接使用该类型。
|
||||
type APIResponse[T any] struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data T `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// APIError 表示后端业务错误(HTTP 状态码可能仍是 200,但 code != 200)。
|
||||
//
|
||||
// 使用 errors.As 判断:
|
||||
//
|
||||
// var apiErr *emailcli.APIError
|
||||
// if errors.As(err, &apiErr) { ... }
|
||||
type APIError struct {
|
||||
Code int
|
||||
Message string
|
||||
Code int // 业务错误码(非 HTTP 状态码)
|
||||
Message string // 错误描述
|
||||
}
|
||||
|
||||
// Error 实现 error 接口。
|
||||
func (e *APIError) Error() string {
|
||||
return fmt.Sprintf("api error %d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
// url 拼接出完整请求 URL。
|
||||
func (c *Client) url(path string) string {
|
||||
return c.baseURL + path
|
||||
}
|
||||
|
||||
// setAuth 根据客户端类型自动写入认证头。
|
||||
func (c *Client) setAuth(req *http.Request) {
|
||||
if c.serviceToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.serviceToken)
|
||||
@@ -86,6 +127,15 @@ func (c *Client) setAuth(req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// doRequest 是所有 API 的底层实现:组装请求 → 发送 → 解包 APIResponse[T]。
|
||||
//
|
||||
// 参数说明:
|
||||
// - method: HTTP 方法(GET/POST/PUT/DELETE)
|
||||
// - path: API 路径(以 / 开头),例如 /api/v1/accounts
|
||||
// - body: 请求体(会被 json.Marshal),无则传 nil
|
||||
// - query: URL 查询参数,通常由 buildQuery 生成
|
||||
//
|
||||
// 返回:解包后的 data 字段。code != 200 时返回 *APIError。
|
||||
func doRequest[T any](c *Client, ctx context.Context, method, path string, body interface{}, query url.Values) (T, error) {
|
||||
var zero T
|
||||
|
||||
@@ -136,18 +186,22 @@ func doRequest[T any](c *Client, ctx context.Context, method, path string, body
|
||||
return apiResp.Data, nil
|
||||
}
|
||||
|
||||
// get 是 doRequest 的 GET 便捷函数。
|
||||
func get[T any](c *Client, ctx context.Context, path string, query url.Values) (T, error) {
|
||||
return doRequest[T](c, ctx, http.MethodGet, path, nil, query)
|
||||
}
|
||||
|
||||
// post 是 doRequest 的 POST 便捷函数。
|
||||
func post[T any](c *Client, ctx context.Context, path string, body interface{}) (T, error) {
|
||||
return doRequest[T](c, ctx, http.MethodPost, path, body, nil)
|
||||
}
|
||||
|
||||
// put 是 doRequest 的 PUT 便捷函数。
|
||||
func put[T any](c *Client, ctx context.Context, path string, body interface{}) (T, error) {
|
||||
return doRequest[T](c, ctx, http.MethodPut, path, body, nil)
|
||||
}
|
||||
|
||||
// del 是 doRequest 的 DELETE 便捷函数。
|
||||
func del[T any](c *Client, ctx context.Context, path string) (T, error) {
|
||||
return doRequest[T](c, ctx, http.MethodDelete, path, nil, nil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user