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  }