github.com/gospider007/requests@v0.0.0-20240506025355-c73d46169a23/body.go (about) 1 package requests 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "fmt" 8 "io" 9 "mime/multipart" 10 "net/http" 11 "net/textproto" 12 "net/url" 13 "reflect" 14 15 "github.com/gospider007/gson" 16 "github.com/gospider007/tools" 17 "golang.org/x/exp/maps" 18 ) 19 20 const ( 21 readType = iota 22 mapType 23 ) 24 25 type OrderMap struct { 26 data map[string]any 27 keys []string 28 } 29 30 func NewOrderMap() *OrderMap { 31 return &OrderMap{ 32 data: make(map[string]any), 33 keys: []string{}, 34 } 35 } 36 37 func (obj *OrderMap) Set(key string, val any) { 38 obj.Del(key) 39 obj.data[key] = val 40 obj.keys = append(obj.keys, key) 41 } 42 func (obj *OrderMap) Del(key string) { 43 delete(obj.data, key) 44 obj.keys = tools.DelSliceVals(obj.keys, key) 45 } 46 func (obj *OrderMap) Keys() []string { 47 return obj.keys 48 } 49 func (obj *OrderMap) parseHeaders() (map[string][]string, []string) { 50 head := make(http.Header) 51 for _, kk := range obj.keys { 52 if vvs, ok := obj.data[kk].([]any); ok { 53 for _, vv := range vvs { 54 head.Add(kk, fmt.Sprint(vv)) 55 } 56 } else { 57 head.Add(kk, fmt.Sprint(obj.data[kk])) 58 } 59 } 60 return head, obj.keys 61 } 62 63 func formWrite(writer *multipart.Writer, key string, val any) (err error) { 64 switch value := val.(type) { 65 case File: 66 h := make(textproto.MIMEHeader) 67 h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes(key), escapeQuotes(value.FileName))) 68 if value.ContentType == "" { 69 switch content := value.Content.(type) { 70 case []byte: 71 h.Set("Content-Type", http.DetectContentType(content)) 72 case string: 73 h.Set("Content-Type", http.DetectContentType(tools.StringToBytes(content))) 74 case io.Reader: 75 h.Set("Content-Type", "application/octet-stream") 76 default: 77 con, err := gson.Encode(content) 78 if err != nil { 79 return err 80 } 81 h.Set("Content-Type", http.DetectContentType(con)) 82 } 83 } else { 84 h.Set("Content-Type", value.ContentType) 85 } 86 var wp io.Writer 87 if wp, err = writer.CreatePart(h); err != nil { 88 return 89 } 90 switch content := value.Content.(type) { 91 case []byte: 92 _, err = wp.Write(content) 93 case string: 94 _, err = wp.Write(tools.StringToBytes(content)) 95 case io.Reader: 96 _, err = io.Copy(wp, content) 97 default: 98 con, err := gson.Encode(content) 99 if err != nil { 100 return err 101 } 102 _, err = wp.Write(con) 103 if err != nil { 104 return err 105 } 106 } 107 case []byte: 108 err = writer.WriteField(key, tools.BytesToString(value)) 109 case string: 110 err = writer.WriteField(key, value) 111 default: 112 con, err := gson.Encode(val) 113 if err != nil { 114 return err 115 } 116 err = writer.WriteField(key, tools.BytesToString(con)) 117 if err != nil { 118 return err 119 } 120 } 121 return 122 } 123 func (obj *OrderMap) parseForm(ctx context.Context) (io.Reader, string, bool, error) { 124 if len(obj.keys) == 0 || len(obj.data) == 0 { 125 return nil, "", false, nil 126 } 127 if obj.isformPip() { 128 pr, pw := pipe(ctx) 129 writer := multipart.NewWriter(pw) 130 go func() { 131 err := obj.formWriteMain(writer) 132 if err == nil { 133 err = io.EOF 134 } 135 pr.Close(err) 136 pw.Close(err) 137 }() 138 return pr, writer.FormDataContentType(), true, nil 139 } 140 body := bytes.NewBuffer(nil) 141 writer := multipart.NewWriter(body) 142 err := obj.formWriteMain(writer) 143 if err != nil { 144 return nil, writer.FormDataContentType(), false, err 145 } 146 return body, writer.FormDataContentType(), false, err 147 } 148 func (obj *OrderMap) isformPip() bool { 149 if len(obj.keys) == 0 || len(obj.data) == 0 { 150 return false 151 } 152 for _, key := range obj.keys { 153 if vals, ok := obj.data[key].([]any); ok { 154 for _, val := range vals { 155 if file, ok := val.(File); ok { 156 if _, ok := file.Content.(io.Reader); ok { 157 return true 158 } 159 } 160 } 161 } else { 162 if file, ok := obj.data[key].(File); ok { 163 if _, ok := file.Content.(io.Reader); ok { 164 return true 165 } 166 } 167 } 168 } 169 return false 170 } 171 func (obj *OrderMap) formWriteMain(writer *multipart.Writer) (err error) { 172 for _, key := range obj.keys { 173 if vals, ok := obj.data[key].([]any); ok { 174 for _, val := range vals { 175 if err = formWrite(writer, key, val); err != nil { 176 return 177 } 178 } 179 } else { 180 if err = formWrite(writer, key, obj.data[key]); err != nil { 181 return 182 } 183 } 184 } 185 return writer.Close() 186 } 187 188 func paramsWrite(buf *bytes.Buffer, key string, val any) { 189 if buf.Len() > 0 { 190 buf.WriteByte('&') 191 } 192 buf.WriteString(url.QueryEscape(key)) 193 buf.WriteByte('=') 194 buf.WriteString(url.QueryEscape(fmt.Sprint(val))) 195 } 196 func (obj *OrderMap) parseParams() *bytes.Buffer { 197 buf := bytes.NewBuffer(nil) 198 for _, k := range obj.keys { 199 if vals, ok := obj.data[k].([]any); ok { 200 for _, v := range vals { 201 paramsWrite(buf, k, v) 202 } 203 } else { 204 paramsWrite(buf, k, obj.data[k]) 205 } 206 } 207 return buf 208 } 209 func (obj *OrderMap) parseData() *bytes.Reader { 210 val := obj.parseParams().Bytes() 211 if val == nil { 212 return nil 213 } 214 return bytes.NewReader(val) 215 } 216 func (obj *OrderMap) MarshalJSON() ([]byte, error) { 217 buf := bytes.NewBuffer(nil) 218 err := buf.WriteByte('{') 219 if err != nil { 220 return nil, err 221 } 222 for i, k := range obj.keys { 223 if i > 0 { 224 if err = buf.WriteByte(','); err != nil { 225 return nil, err 226 } 227 } 228 key, err := gson.Encode(k) 229 if err != nil { 230 return nil, err 231 } 232 if _, err = buf.Write(key); err != nil { 233 return nil, err 234 } 235 if err = buf.WriteByte(':'); err != nil { 236 return nil, err 237 } 238 val, err := gson.Encode(obj.data[k]) 239 if err != nil { 240 return nil, err 241 } 242 if _, err = buf.Write(val); err != nil { 243 return nil, err 244 } 245 } 246 if err = buf.WriteByte('}'); err != nil { 247 return nil, err 248 } 249 return buf.Bytes(), nil 250 } 251 252 func any2Map(val any) map[string]any { 253 if reflect.TypeOf(val).Kind() != reflect.Map { 254 return nil 255 } 256 mapValue := reflect.ValueOf(val) 257 result := make(map[string]any) 258 for _, key := range mapValue.MapKeys() { 259 valueData := mapValue.MapIndex(key).Interface() 260 sliceValue := reflect.ValueOf(valueData) 261 if sliceValue.Kind() == reflect.Slice { 262 valueData2 := []any{} 263 for i := 0; i < sliceValue.Len(); i++ { 264 valueData2 = append(valueData2, sliceValue.Index(i).Interface()) 265 } 266 result[fmt.Sprint(key.Interface())] = valueData2 267 } else { 268 result[fmt.Sprint(key.Interface())] = valueData 269 } 270 } 271 return result 272 } 273 274 func (obj *RequestOption) newBody(val any, valType int) (reader io.Reader, parseOrderMap *OrderMap, orderKey []string, err error) { 275 var isOrderMap bool 276 parseOrderMap, isOrderMap = val.(*OrderMap) 277 if isOrderMap { 278 if valType == readType { 279 readCon, err := parseOrderMap.MarshalJSON() 280 return bytes.NewReader(readCon), nil, nil, err 281 } else { 282 return nil, parseOrderMap, parseOrderMap.Keys(), nil 283 } 284 } 285 if valType == readType { 286 switch value := val.(type) { 287 case io.Reader: 288 obj.once = true 289 return value, nil, nil, nil 290 case string: 291 return bytes.NewReader(tools.StringToBytes(value)), nil, nil, nil 292 case []byte: 293 return bytes.NewReader(value), nil, nil, nil 294 default: 295 enData, err := gson.Encode(val) 296 if err != nil { 297 return nil, nil, nil, err 298 } 299 return bytes.NewReader(enData), nil, nil, nil 300 } 301 } 302 if mapData := any2Map(val); mapData != nil { 303 val = mapData 304 } 305 mapL: 306 switch value := val.(type) { 307 case *gson.Client: 308 if !value.IsObject() { 309 return nil, nil, nil, errors.New("body-type error") 310 } 311 orderMap := NewOrderMap() 312 for kk, vv := range value.Map() { 313 if vv.IsArray() { 314 valData := make([]any, len(vv.Array())) 315 for i, v := range vv.Array() { 316 valData[i] = v.Value() 317 } 318 orderMap.Set(kk, valData) 319 } else { 320 orderMap.Set(kk, vv.Value()) 321 } 322 } 323 return nil, orderMap, nil, nil 324 case *OrderMap: 325 if mapData := any2Map(value.data); mapData != nil { 326 value.data = mapData 327 } 328 return nil, value, nil, nil 329 case map[string]any: 330 orderMap := NewOrderMap() 331 orderMap.data = value 332 orderMap.keys = maps.Keys(value) 333 return nil, orderMap, nil, nil 334 } 335 if val, err = gson.Decode(val); err != nil { 336 switch value := val.(type) { 337 case string: 338 return bytes.NewReader(tools.StringToBytes(value)), nil, nil, nil 339 case []byte: 340 return bytes.NewReader(value), nil, nil, nil 341 default: 342 return nil, nil, nil, err 343 } 344 } 345 goto mapL 346 }