package request import ( "bytes" "context" "fmt" "io" "net/http" "time" ) type Options struct { Headers http.Header StatusCodeFunc func(int) bool HttpClient *http.Client } func NewOptions(options ...Option) *Options { o := &Options{ Headers: http.Header{ "Content-Type": []string{"application/json"}, }, StatusCodeFunc: func(code int) bool { return code == http.StatusOK }, HttpClient: &http.Client{ Timeout: 10 * time.Second, //Transport: &http.Transport{ // MaxIdleConns: 100, // 最大空闲连接数 // MaxIdleConnsPerHost: 20, // 每个主机的最大空闲连接数 // IdleConnTimeout: 30 * time.Second, // 空闲连接超时时间 //}, }, } for _, option := range options { option(o) } return o } type Option func(*Options) func WithHttpClient(httpClient *http.Client) Option { return func(options *Options) { options.HttpClient = httpClient } } func WithHeaders(headers http.Header) Option { return func(options *Options) { options.Headers = headers } } func WithStatusCodeFunc(statusCodeFunc func(int) bool) Option { return func(options *Options) { options.StatusCodeFunc = statusCodeFunc } } func POST(ctx context.Context, url string, body []byte, options *Options) (http.Header, []byte, error) { return Request(ctx, http.MethodPost, url, body, options) } func GET(ctx context.Context, url string, options *Options) (http.Header, []byte, error) { return Request(ctx, http.MethodGet, url, nil, options) } func PUT(ctx context.Context, url string, body []byte, options *Options) (http.Header, []byte, error) { return Request(ctx, http.MethodPut, url, body, options) } func Post(ctx context.Context, url string, body []byte, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodPost, url, body, NewOptions(options...)) } func Get(ctx context.Context, url string, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodGet, url, nil, NewOptions(options...)) } func Put(ctx context.Context, url string, body []byte, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodPut, url, body, NewOptions(options...)) } func Request(_ context.Context, method, url string, body []byte, o *Options) (http.Header, []byte, error) { req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { return nil, nil, fmt.Errorf("创建HTTP请求失败: %w", err) } req.Header = o.Headers // 使用共享客户端 resp, err := o.HttpClient.Do(req) if err != nil { return nil, nil, fmt.Errorf("发送请求失败,err:%w", err) } defer resp.Body.Close() bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return nil, nil, fmt.Errorf("读取响应体失败: %w", err) } if !o.StatusCodeFunc(resp.StatusCode) { return nil, nil, fmt.Errorf("请求异常:%s", resp.Status) } return resp.Header, bodyBytes, nil }