docs(README): 更新文档为中文并完善API参考

- 将README从英文翻译为中文
- 添加详细的API参考文档,包括所有管理接口和枚举值说明
- 补充安装、快速开始、认证方式等使用指南

refactor(client): 优化客户端代码结构并添加详细注释

- 为所有API方法添加中文注释和使用说明
- 改进Client结构体和Option配置的设计
- 统一错误处理和响应结构的文档说明
This commit is contained in:
shiran
2026-04-18 15:54:19 +08:00
parent fe19922eff
commit fe43b9bdce
15 changed files with 1013 additions and 291 deletions
+63 -9
View File
@@ -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)
}