package userManagement import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "net/url" "time" ) // Client API 客户端 type Client struct { baseURL string httpClient *http.Client accessToken string apiKey string } // ClientOption 配置选项 type ClientOption func(*Client) // WithAPIToken 设置 API Token(用于简单认证) func WithAPIToken(token string) ClientOption { return func(c *Client) { c.apiKey = token } } // WithAccessToken 设置 Access Token(用于已认证请求) func WithAccessToken(token string) ClientOption { return func(c *Client) { c.accessToken = token } } // WithHTTPClient 设置自定义 HTTP 客户端 func WithHTTPClient(httpClient *http.Client) ClientOption { return func(c *Client) { c.httpClient = httpClient } } // NewClient 创建新的 API 客户端 func NewClient(baseURL string, opts ...ClientOption) *Client { c := &Client{ baseURL: baseURL, httpClient: &http.Client{ Timeout: 30 * time.Second, }, } for _, opt := range opts { opt(c) } return c } // APIResponse 标准 API 响应 type APIResponse struct { Code int `json:"code"` Message string `json:"message"` Data json.RawMessage `json:"data,omitempty"` } // ErrorResponse 错误响应 type ErrorResponse struct { Code int `json:"code"` Message string `json:"message"` } func (c *Client) doRequest(ctx context.Context, method, path string, body interface{}) (*http.Response, error) { u, err := url.JoinPath(c.baseURL, path) if err != nil { return nil, fmt.Errorf("failed to join URL: %w", err) } var reqBody io.Reader if body != nil { jsonData, err := json.Marshal(body) if err != nil { return nil, fmt.Errorf("failed to marshal request body: %w", err) } reqBody = bytes.NewReader(jsonData) } req, err := http.NewRequestWithContext(ctx, method, u, reqBody) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") if c.accessToken != "" { req.Header.Set("Authorization", "Bearer "+c.accessToken) } else if c.apiKey != "" { req.Header.Set("X-API-Key", c.apiKey) } return c.httpClient.Do(req) } func (c *Client) parseResponse(resp *http.Response, result interface{}) error { defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("failed to read response body: %w", err) } if resp.StatusCode >= 400 { var errResp ErrorResponse if err := json.Unmarshal(body, &errResp); err == nil { return fmt.Errorf("API error %d: %s", resp.StatusCode, errResp.Message) } return fmt.Errorf("API error %d: %s", resp.StatusCode, string(body)) } if result == nil { return nil } var apiResp APIResponse if err := json.Unmarshal(body, &apiResp); err != nil { return fmt.Errorf("failed to unmarshal response: %w", err) } if apiResp.Data != nil { if err := json.Unmarshal(apiResp.Data, result); err != nil { return fmt.Errorf("failed to unmarshal data: %w", err) } } return nil } // SetAccessToken 设置访问令牌 func (c *Client) SetAccessToken(token string) { c.accessToken = token }