58 lines
1.7 KiB
Go
58 lines
1.7 KiB
Go
package httpclient
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
// FastHTTPClient 使用 fasthttp 实现 HTTPClient 接口
|
|
type FastHTTPClient struct {
|
|
client *fasthttp.Client
|
|
reqPool *sync.Pool
|
|
respPool *sync.Pool
|
|
}
|
|
|
|
// NewFastHTTPClient 返回一个初始化的 FastHTTPClient
|
|
func NewFastHTTPClient() *FastHTTPClient {
|
|
return &FastHTTPClient{
|
|
client: &fasthttp.Client{},
|
|
reqPool: &sync.Pool{New: func() interface{} { return new(fasthttp.Request) }},
|
|
respPool: &sync.Pool{New: func() interface{} { return new(fasthttp.Response) }},
|
|
}
|
|
}
|
|
|
|
// Do 发送非流式请求
|
|
func (c *FastHTTPClient) Do(req *Request) (*Response, error) {
|
|
fr := c.reqPool.Get().(*fasthttp.Request)
|
|
defer c.reqPool.Put(fr)
|
|
fr.Header.SetMethod(req.Method)
|
|
fr.SetRequestURI(req.URL)
|
|
if len(req.Body) > 0 {
|
|
fr.SetBody(req.Body)
|
|
}
|
|
for k, v := range req.Headers {
|
|
fr.Header.Set(k, v)
|
|
}
|
|
fresp := c.respPool.Get().(*fasthttp.Response)
|
|
defer c.respPool.Put(fresp)
|
|
if err := c.client.Do(fr, fresp); err != nil {
|
|
return nil, err
|
|
}
|
|
resp := &Response{
|
|
StatusCode: fresp.StatusCode(),
|
|
Body: append([]byte(nil), fresp.Body()...),
|
|
Headers: make(map[string]string),
|
|
}
|
|
fresp.Header.VisitAll(func(k, v []byte) {
|
|
resp.Headers[string(k)] = string(v)
|
|
})
|
|
return resp, nil
|
|
}
|
|
|
|
// Stream 发送流式请求,逐块通过 callback 回调 SSE 数据
|
|
// 目前使用 net/http 实现 SSE 解析,后续可优化为 fasthttp 原生实现
|
|
func (c *FastHTTPClient) Stream(req *Request, callback func(chunk SSEChunk) error) error {
|
|
return NewNetHTTPClient().Stream(req, callback)
|
|
}
|