requests.go 2.4 KB

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