package httpclient import ( "bufio" "bytes" "io" "net/http" "strings" "time" ) // NetHTTPClient 使用 net/http 实现 HTTPClient 接口 type NetHTTPClient struct { client *http.Client // 可根据需要添加对象池 } // NewNetHTTPClient 返回一个初始化的 NetHTTPClient func NewNetHTTPClient() *NetHTTPClient { return &NetHTTPClient{client: &http.Client{}} } // Do 发送非流式请求 func (c *NetHTTPClient) Do(req *Request) (*Response, error) { r, err := http.NewRequest(req.Method, req.URL, bytes.NewReader(req.Body)) if err != nil { return nil, err } for k, v := range req.Headers { r.Header.Set(k, v) } resp, err := c.client.Do(r) if err != nil { return nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } headers := make(map[string]string) for k, v := range resp.Header { headers[k] = v[0] } return &Response{StatusCode: resp.StatusCode, Body: body, Headers: headers}, nil } // Stream 发送流式请求,逐块通过 callback 回调 SSE 数据 func (c *NetHTTPClient) Stream(req *Request, callback func(chunk SSEChunk) error) error { r, err := http.NewRequest(req.Method, req.URL, bytes.NewReader(req.Body)) if err != nil { return err } for k, v := range req.Headers { r.Header.Set(k, v) } resp, err := c.client.Do(r) if err != nil { return err } defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { text := scanner.Text() if text == "" { continue } const prefix = "data: " if strings.HasPrefix(text, prefix) { payload := text[len(prefix):] isDone := payload == "[DONE]" var dataBytes []byte if !isDone { dataBytes = []byte(payload) } chunk := SSEChunk{ Data: dataBytes, Timestamp: time.Now().UnixNano(), IsDone: isDone, } if err := callback(chunk); err != nil { return err } } } if err := scanner.Err(); err != nil { return err } return nil }