package starnet import ( "encoding/json" "io" "os" ) // SetBody 设置请求体(字节) func (r *Request) SetBody(body []byte) *Request { if r.err != nil { return r } if r.doRaw { return r } setBytesBodyConfig(&r.config.Body, body) r.invalidatePreparedState() return r } // SetBodyReader 设置请求体(Reader)。 // 出于避免重复写的保守策略,Reader 形态的 body 在非幂等方法上不会自动参与 retry。 func (r *Request) SetBodyReader(reader io.Reader) *Request { if r.err != nil { return r } if r.doRaw { return r } setReaderBodyConfig(&r.config.Body, reader) r.invalidatePreparedState() return r } // SetBodyString 设置请求体(字符串) func (r *Request) SetBodyString(body string) *Request { return r.SetBody([]byte(body)) } // SetJSON 设置 JSON 请求体 func (r *Request) SetJSON(v interface{}) *Request { if r.err != nil { return r } data, err := json.Marshal(v) if err != nil { r.err = wrapError(err, "marshal json") return r } return r.SetContentType(ContentTypeJSON).SetBody(data) } // SetFormData 设置表单数据(覆盖) func (r *Request) SetFormData(data map[string][]string) *Request { if r.err != nil { return r } if r.doRaw { return r } setFormBodyConfig(&r.config.Body, data) r.invalidatePreparedState() return r } // AddFormData 添加表单数据 func (r *Request) AddFormData(key, value string) *Request { if r.err != nil { return r } if r.doRaw { return r } ensureFormMode(&r.config.Body) r.config.Body.FormData[key] = append(r.config.Body.FormData[key], value) r.invalidatePreparedState() return r } // AddFormDataMap 批量添加表单数据 func (r *Request) AddFormDataMap(data map[string]string) *Request { if r.err != nil { return r } if r.doRaw { return r } ensureFormMode(&r.config.Body) for key, value := range data { r.config.Body.FormData[key] = append(r.config.Body.FormData[key], value) } r.invalidatePreparedState() return r } // AddFile 添加文件(从路径) func (r *Request) AddFile(formName, filePath string) *Request { if r.err != nil { return r } stat, err := os.Stat(filePath) if err != nil { r.err = wrapError(ErrFileNotFound, "file: %s", filePath) return r } 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, }) r.invalidatePreparedState() return r } // AddFileWithName 添加文件(指定文件名) func (r *Request) AddFileWithName(formName, filePath, fileName string) *Request { if r.err != nil { return r } stat, err := os.Stat(filePath) if err != nil { r.err = wrapError(ErrFileNotFound, "file: %s", filePath) return r } ensureMultipartMode(&r.config.Body) r.config.Body.Files = append(r.config.Body.Files, RequestFile{ FormName: formName, FileName: fileName, FilePath: filePath, FileSize: stat.Size(), FileType: ContentTypeOctetStream, }) r.invalidatePreparedState() return r } // AddFileWithType 添加文件(指定 MIME 类型) func (r *Request) AddFileWithType(formName, filePath, fileType string) *Request { if r.err != nil { return r } stat, err := os.Stat(filePath) if err != nil { r.err = wrapError(ErrFileNotFound, "file: %s", filePath) return r } 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: fileType, }) r.invalidatePreparedState() return r } // AddFileStream 添加文件流 func (r *Request) AddFileStream(formName, fileName string, size int64, reader io.Reader) *Request { if r.err != nil { return r } if reader == nil { r.err = ErrNilReader return r } ensureMultipartMode(&r.config.Body) r.config.Body.Files = append(r.config.Body.Files, RequestFile{ FormName: formName, FileName: fileName, FileData: reader, FileSize: size, FileType: ContentTypeOctetStream, }) r.invalidatePreparedState() return r } // AddFileStreamWithType 添加文件流(指定 MIME 类型) func (r *Request) AddFileStreamWithType(formName, fileName, fileType string, size int64, reader io.Reader) *Request { if r.err != nil { return r } if reader == nil { r.err = ErrNilReader return r } ensureMultipartMode(&r.config.Body) r.config.Body.Files = append(r.config.Body.Files, RequestFile{ FormName: formName, FileName: fileName, FileData: reader, FileSize: size, FileType: fileType, }) r.invalidatePreparedState() return r }