package starnet import ( "encoding/json" "io" "os" ) // WithBody 设置请求体(字节) func WithBody(body []byte) RequestOpt { return func(r *Request) error { setBytesBodyConfig(&r.config.Body, body) return nil } } // WithBodyString 设置请求体(字符串) func WithBodyString(body string) RequestOpt { return func(r *Request) error { setBytesBodyConfig(&r.config.Body, []byte(body)) return nil } } // WithBodyReader 设置请求体(Reader)。 // 出于避免重复写的保守策略,Reader 形态的 body 在非幂等方法上不会自动参与 retry。 func WithBodyReader(reader io.Reader) RequestOpt { return func(r *Request) error { setReaderBodyConfig(&r.config.Body, reader) return nil } } // WithJSON 设置 JSON 请求体 func WithJSON(v interface{}) RequestOpt { return func(r *Request) error { data, err := json.Marshal(v) if err != nil { return wrapError(err, "marshal json") } r.config.Headers.Set("Content-Type", ContentTypeJSON) setBytesBodyConfig(&r.config.Body, data) return nil } } // WithFormData 设置表单数据 func WithFormData(data map[string][]string) RequestOpt { return func(r *Request) error { setFormBodyConfig(&r.config.Body, data) return nil } } // WithFormDataMap 设置表单数据(简化版) func WithFormDataMap(data map[string]string) RequestOpt { return func(r *Request) error { setFormBodyConfig(&r.config.Body, nil) for key, value := range data { r.config.Body.FormData[key] = []string{value} } return nil } } // WithAddFormData 添加表单数据 func WithAddFormData(key, value string) RequestOpt { return func(r *Request) error { ensureFormMode(&r.config.Body) r.config.Body.FormData[key] = append(r.config.Body.FormData[key], value) return nil } } // WithFile 添加文件 func WithFile(formName, filePath string) RequestOpt { return func(r *Request) error { stat, err := os.Stat(filePath) if err != nil { return wrapError(ErrFileNotFound, "file: %s", filePath) } ensureMultipartMode(&r.config.Body) r.config.Body.Files = append(r.config.Body.Files, RequestFile{ FormName: formName, FileName: stat.Name(), FilePath: filePath, FileSize: stat.Size(), FileType: ContentTypeOctetStream, }) return nil } } // WithFileStream 添加文件流 func WithFileStream(formName, fileName string, size int64, reader io.Reader) RequestOpt { return func(r *Request) error { if reader == nil { return ErrNilReader } ensureMultipartMode(&r.config.Body) r.config.Body.Files = append(r.config.Body.Files, RequestFile{ FormName: formName, FileName: fileName, FileData: reader, FileSize: size, FileType: ContentTypeOctetStream, }) return nil } }