You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

http.go 6.5 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. package http
  2. import (
  3. "fmt"
  4. "io"
  5. "mime/multipart"
  6. "net/http"
  7. ul "net/url"
  8. "strings"
  9. "gitlink.org.cn/cloudream/common/pkgs/iterator"
  10. "gitlink.org.cn/cloudream/common/utils/serder"
  11. )
  12. const (
  13. ContentTypeJSON = "application/json"
  14. ContentTypeForm = "application/x-www-form-urlencoded"
  15. ContentTypeMultiPart = "multipart/form-data"
  16. ContentTypeOctetStream = "application/octet-stream"
  17. )
  18. type RequestParam struct {
  19. Header any
  20. Query any
  21. Body any
  22. }
  23. func GetJSON(url string, param RequestParam) (*http.Response, error) {
  24. req, err := http.NewRequest(http.MethodGet, url, nil)
  25. if err != nil {
  26. return nil, err
  27. }
  28. if err = prepareQuery(req, param.Query); err != nil {
  29. return nil, err
  30. }
  31. if err = prepareHeader(req, param.Header); err != nil {
  32. return nil, err
  33. }
  34. if err = prepareJSONBody(req, param.Body); err != nil {
  35. return nil, err
  36. }
  37. return http.DefaultClient.Do(req)
  38. }
  39. func GetForm(url string, param RequestParam) (*http.Response, error) {
  40. req, err := http.NewRequest(http.MethodGet, url, nil)
  41. if err != nil {
  42. return nil, err
  43. }
  44. if err = prepareQuery(req, param.Query); err != nil {
  45. return nil, err
  46. }
  47. if err = prepareHeader(req, param.Header); err != nil {
  48. return nil, err
  49. }
  50. if err = prepareFormBody(req, param.Body); err != nil {
  51. return nil, err
  52. }
  53. return http.DefaultClient.Do(req)
  54. }
  55. func PostJSON(url string, param RequestParam) (*http.Response, error) {
  56. req, err := http.NewRequest(http.MethodPost, url, nil)
  57. if err != nil {
  58. return nil, err
  59. }
  60. if err = prepareQuery(req, param.Query); err != nil {
  61. return nil, err
  62. }
  63. if err = prepareHeader(req, param.Header); err != nil {
  64. return nil, err
  65. }
  66. if err = prepareJSONBody(req, param.Body); err != nil {
  67. return nil, err
  68. }
  69. return http.DefaultClient.Do(req)
  70. }
  71. func PostForm(url string, param RequestParam) (*http.Response, error) {
  72. req, err := http.NewRequest(http.MethodPost, url, nil)
  73. if err != nil {
  74. return nil, err
  75. }
  76. if err = prepareQuery(req, param.Query); err != nil {
  77. return nil, err
  78. }
  79. if err = prepareHeader(req, param.Header); err != nil {
  80. return nil, err
  81. }
  82. if err = prepareFormBody(req, param.Body); err != nil {
  83. return nil, err
  84. }
  85. return http.DefaultClient.Do(req)
  86. }
  87. func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) {
  88. var ret TBody
  89. contType := resp.Header.Get("Content-Type")
  90. if strings.Contains(contType, ContentTypeJSON) {
  91. if err := serder.JSONToObjectStream(resp.Body, &ret); err != nil {
  92. return ret, fmt.Errorf("parsing response: %w", err)
  93. }
  94. return ret, nil
  95. }
  96. return ret, fmt.Errorf("unknow response content type: %s", contType)
  97. }
  98. type MultiPartRequestParam struct {
  99. Header any
  100. Query any
  101. Form any
  102. Files MultiPartFileIterator
  103. }
  104. type MultiPartFileIterator = iterator.Iterator[*IterMultiPartFile]
  105. type IterMultiPartFile struct {
  106. FieldName string // 这个文件所属的form字段
  107. FileName string // 文件名
  108. File io.ReadCloser
  109. }
  110. func PostMultiPart(url string, param MultiPartRequestParam) (*http.Response, error) {
  111. req, err := http.NewRequest(http.MethodPost, url, nil)
  112. if err != nil {
  113. return nil, err
  114. }
  115. if err = prepareQuery(req, param.Query); err != nil {
  116. return nil, err
  117. }
  118. if err = prepareHeader(req, param.Header); err != nil {
  119. return nil, err
  120. }
  121. pr, pw := io.Pipe()
  122. muWriter := multipart.NewWriter(pw)
  123. setHeader(req.Header, "Content-Type", fmt.Sprintf("%s;boundary=%s", ContentTypeMultiPart, muWriter.Boundary()))
  124. writeResult := make(chan error, 1)
  125. go func() {
  126. writeResult <- func() error {
  127. defer pw.Close()
  128. defer muWriter.Close()
  129. if param.Form != nil {
  130. mp, err := serder.ObjectToMap(param.Form)
  131. if err != nil {
  132. return fmt.Errorf("formValues object to map failed, err: %w", err)
  133. }
  134. for k, v := range mp {
  135. err := muWriter.WriteField(k, fmt.Sprintf("%v", v))
  136. if err != nil {
  137. return fmt.Errorf("write form field failed, err: %w", err)
  138. }
  139. }
  140. }
  141. for {
  142. file, err := param.Files.MoveNext()
  143. if err == iterator.ErrNoMoreItem {
  144. break
  145. }
  146. if err != nil {
  147. return fmt.Errorf("opening file: %w", err)
  148. }
  149. err = func() error {
  150. defer file.File.Close()
  151. w, err := muWriter.CreateFormFile(file.FieldName, file.FileName)
  152. if err != nil {
  153. return fmt.Errorf("create form file failed, err: %w", err)
  154. }
  155. _, err = io.Copy(w, file.File)
  156. if err != nil {
  157. return err
  158. }
  159. return nil
  160. }()
  161. if err != nil {
  162. return err
  163. }
  164. }
  165. return nil
  166. }()
  167. }()
  168. req.Body = pr
  169. cli := http.Client{}
  170. resp, err := cli.Do(req)
  171. if err != nil {
  172. return nil, err
  173. }
  174. writeErr := <-writeResult
  175. if writeErr != nil {
  176. return nil, writeErr
  177. }
  178. return resp, nil
  179. }
  180. func prepareQuery(req *http.Request, query any) error {
  181. if query == nil {
  182. return nil
  183. }
  184. mp, ok := query.(map[string]any)
  185. if !ok {
  186. var err error
  187. if mp, err = serder.ObjectToMap(query); err != nil {
  188. return fmt.Errorf("query object to map: %w", err)
  189. }
  190. }
  191. values := make(ul.Values)
  192. for k, v := range mp {
  193. values.Add(k, fmt.Sprintf("%v", v))
  194. }
  195. req.URL.RawQuery = values.Encode()
  196. return nil
  197. }
  198. func prepareHeader(req *http.Request, header any) error {
  199. if header == nil {
  200. return nil
  201. }
  202. mp, ok := header.(map[string]any)
  203. if !ok {
  204. var err error
  205. if mp, err = serder.ObjectToMap(header); err != nil {
  206. return fmt.Errorf("header object to map: %w", err)
  207. }
  208. }
  209. req.Header = make(http.Header)
  210. for k, v := range mp {
  211. req.Header.Set(k, fmt.Sprintf("%v", v))
  212. }
  213. return nil
  214. }
  215. func prepareJSONBody(req *http.Request, body any) error {
  216. setHeader(req.Header, "Content-Type", ContentTypeJSON)
  217. if body == nil {
  218. return nil
  219. }
  220. req.Body = serder.ObjectToJSONStream(body)
  221. return nil
  222. }
  223. func prepareFormBody(req *http.Request, body any) error {
  224. setHeader(req.Header, "Content-Type", ContentTypeForm)
  225. if body == nil {
  226. return nil
  227. }
  228. mp, ok := body.(map[string]any)
  229. if !ok {
  230. var err error
  231. if mp, err = serder.ObjectToMap(body); err != nil {
  232. return fmt.Errorf("body object to map: %w", err)
  233. }
  234. }
  235. values := make(ul.Values)
  236. for k, v := range mp {
  237. values.Add(k, fmt.Sprintf("%v", v))
  238. }
  239. req.Body = io.NopCloser(strings.NewReader(values.Encode()))
  240. return nil
  241. }
  242. func setHeader(mp http.Header, key, value string) http.Header {
  243. if mp == nil {
  244. mp = make(http.Header)
  245. }
  246. mp.Set(key, value)
  247. return mp
  248. }
  249. func setValue(values ul.Values, key, value string) ul.Values {
  250. if values == nil {
  251. values = make(ul.Values)
  252. }
  253. values.Add(key, value)
  254. return values
  255. }