package client import ( "bytes" "context" "encoding/json" "errors" "net/http" "ds2api/internal/config" trans "ds2api/internal/deepseek/transport" ) func (c *Client) postJSON(ctx context.Context, doer trans.Doer, fallback trans.Doer, url string, headers map[string]string, payload any) (map[string]any, error) { body, status, err := c.postJSONWithStatus(ctx, doer, fallback, url, headers, payload) if err != nil { return nil, err } if status == 0 { return nil, errors.New("request failed") } return body, nil } func (c *Client) postJSONWithStatus(ctx context.Context, doer trans.Doer, fallback trans.Doer, url string, headers map[string]string, payload any) (map[string]any, int, error) { b, err := json.Marshal(payload) if err != nil { return nil, 0, err } headers = c.jsonHeaders(headers) req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) if err != nil { return nil, 0, err } for k, v := range headers { req.Header.Set(k, v) } resp, err := doer.Do(req) if err != nil { config.Logger.Warn("[deepseek] fingerprint request failed, fallback to std transport", "url", url, "error", err) req2, reqErr := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) if reqErr != nil { return nil, 0, reqErr } for k, v := range headers { req2.Header.Set(k, v) } resp, err = fallback.Do(req2) if err != nil { return nil, 0, err } } defer func() { _ = resp.Body.Close() }() payloadBytes, err := readResponseBody(resp) if err != nil { return nil, resp.StatusCode, err } out := map[string]any{} if len(payloadBytes) > 0 { if err := json.Unmarshal(payloadBytes, &out); err != nil { config.Logger.Warn("[deepseek] json parse failed", "url", url, "status", resp.StatusCode, "content_encoding", resp.Header.Get("Content-Encoding"), "preview", preview(payloadBytes)) } } return out, resp.StatusCode, nil } func (c *Client) getJSONWithStatus(ctx context.Context, doer trans.Doer, url string, headers map[string]string) (map[string]any, int, error) { clients := c.requestClientsFromContext(ctx) req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return nil, 0, err } for k, v := range headers { req.Header.Set(k, v) } resp, err := doer.Do(req) if err != nil { config.Logger.Warn("[deepseek] fingerprint GET request failed, fallback to std transport", "url", url, "error", err) req2, reqErr := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if reqErr != nil { return nil, 0, reqErr } for k, v := range headers { req2.Header.Set(k, v) } resp, err = clients.fallback.Do(req2) if err != nil { return nil, 0, err } } defer func() { _ = resp.Body.Close() }() payloadBytes, err := readResponseBody(resp) if err != nil { return nil, resp.StatusCode, err } out := map[string]any{} if len(payloadBytes) > 0 { if err := json.Unmarshal(payloadBytes, &out); err != nil { config.Logger.Warn("[deepseek] json parse failed", "url", url, "status", resp.StatusCode, "content_encoding", resp.Header.Get("Content-Encoding"), "preview", preview(payloadBytes)) } } return out, resp.StatusCode, nil }