package request import ( "bytes" "context" "fmt" "io" "net/http" "time" ) // Options 用于配置请求的各种选项 type Options struct { Headers http.Header StatusCodeFunc func(int) bool Timeout time.Duration } // Option 是一个函数类型,用于设置RequestOptions的各个字段 type Option func(*Options) // WithTimeout 设置请求超时时间的选项函数 func WithTimeout(timeout time.Duration) Option { return func(options *Options) { options.Timeout = timeout } } // WithHeaders 设置请求头的选项函数 func WithHeaders(headers http.Header) Option { return func(options *Options) { options.Headers = headers } } // WithStatusCodeFunc 设置自定义状态码处理函数的选项函数 func WithStatusCodeFunc(statusCodeFunc func(int) bool) Option { return func(options *Options) { options.StatusCodeFunc = statusCodeFunc } } func Post(ctx context.Context, url string, body []byte, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodPost, url, body, options...) } func Get(ctx context.Context, url string, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodGet, url, nil, options...) } func Put(ctx context.Context, url string, body []byte, options ...Option) (http.Header, []byte, error) { return Request(ctx, http.MethodPut, url, body, options...) } func Request(_ context.Context, method, url string, body []byte, options ...Option) (http.Header, []byte, error) { o := &Options{ Headers: http.Header{ "Content-Type": []string{"application/json"}, }, Timeout: 15 * time.Second, StatusCodeFunc: func(code int) bool { return code == http.StatusOK }, } for _, option := range options { option(o) } req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { return nil, nil, fmt.Errorf("创建HTTP请求失败: %w", err) } req.Header = o.Headers httpClient := &http.Client{ Timeout: o.Timeout, } resp, err := httpClient.Do(req) if err != nil { return nil, nil, fmt.Errorf("发送HTTP请求失败: %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 }