requests.go 2.6 KB

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