github.com/lingyao2333/mo-zero@v1.4.1/rest/httpx/requests.go (about)

     1  package httpx
     2  
     3  import (
     4  	"io"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/lingyao2333/mo-zero/core/mapping"
     9  	"github.com/lingyao2333/mo-zero/rest/internal/encoding"
    10  	"github.com/lingyao2333/mo-zero/rest/internal/header"
    11  	"github.com/lingyao2333/mo-zero/rest/pathvar"
    12  )
    13  
    14  const (
    15  	formKey           = "form"
    16  	pathKey           = "path"
    17  	maxMemory         = 32 << 20 // 32MB
    18  	maxBodyLen        = 8 << 20  // 8MB
    19  	separator         = ";"
    20  	tokensInAttribute = 2
    21  )
    22  
    23  var (
    24  	formUnmarshaler = mapping.NewUnmarshaler(formKey, mapping.WithStringValues())
    25  	pathUnmarshaler = mapping.NewUnmarshaler(pathKey, mapping.WithStringValues())
    26  )
    27  
    28  // Parse parses the request.
    29  func Parse(r *http.Request, v interface{}) error {
    30  	if err := ParsePath(r, v); err != nil {
    31  		return err
    32  	}
    33  
    34  	if err := ParseForm(r, v); err != nil {
    35  		return err
    36  	}
    37  
    38  	if err := ParseHeaders(r, v); err != nil {
    39  		return err
    40  	}
    41  
    42  	return ParseJsonBody(r, v)
    43  }
    44  
    45  // ParseHeaders parses the headers request.
    46  func ParseHeaders(r *http.Request, v interface{}) error {
    47  	return encoding.ParseHeaders(r.Header, v)
    48  }
    49  
    50  // ParseForm parses the form request.
    51  func ParseForm(r *http.Request, v interface{}) error {
    52  	params, err := GetFormValues(r)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	return formUnmarshaler.Unmarshal(params, v)
    58  }
    59  
    60  // ParseHeader parses the request header and returns a map.
    61  func ParseHeader(headerValue string) map[string]string {
    62  	ret := make(map[string]string)
    63  	fields := strings.Split(headerValue, separator)
    64  
    65  	for _, field := range fields {
    66  		field = strings.TrimSpace(field)
    67  		if len(field) == 0 {
    68  			continue
    69  		}
    70  
    71  		kv := strings.SplitN(field, "=", tokensInAttribute)
    72  		if len(kv) != tokensInAttribute {
    73  			continue
    74  		}
    75  
    76  		ret[kv[0]] = kv[1]
    77  	}
    78  
    79  	return ret
    80  }
    81  
    82  // ParseJsonBody parses the post request which contains json in body.
    83  func ParseJsonBody(r *http.Request, v interface{}) error {
    84  	if withJsonBody(r) {
    85  		reader := io.LimitReader(r.Body, maxBodyLen)
    86  		return mapping.UnmarshalJsonReader(reader, v)
    87  	}
    88  
    89  	return mapping.UnmarshalJsonMap(nil, v)
    90  }
    91  
    92  // ParsePath parses the symbols reside in url path.
    93  // Like http://localhost/bag/:name
    94  func ParsePath(r *http.Request, v interface{}) error {
    95  	vars := pathvar.Vars(r)
    96  	m := make(map[string]interface{}, len(vars))
    97  	for k, v := range vars {
    98  		m[k] = v
    99  	}
   100  
   101  	return pathUnmarshaler.Unmarshal(m, v)
   102  }
   103  
   104  func withJsonBody(r *http.Request) bool {
   105  	return r.ContentLength > 0 && strings.Contains(r.Header.Get(header.ContentType), header.ApplicationJson)
   106  }