gin.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package common
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "mime/multipart"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "time"
  11. "github.com/QuantumNous/new-api/constant"
  12. "github.com/gin-gonic/gin"
  13. )
  14. const KeyRequestBody = "key_request_body"
  15. func GetRequestBody(c *gin.Context) ([]byte, error) {
  16. requestBody, _ := c.Get(KeyRequestBody)
  17. if requestBody != nil {
  18. return requestBody.([]byte), nil
  19. }
  20. requestBody, err := io.ReadAll(c.Request.Body)
  21. if err != nil {
  22. return nil, err
  23. }
  24. _ = c.Request.Body.Close()
  25. c.Set(KeyRequestBody, requestBody)
  26. return requestBody.([]byte), nil
  27. }
  28. func UnmarshalBodyReusable(c *gin.Context, v any) error {
  29. requestBody, err := GetRequestBody(c)
  30. if err != nil {
  31. return err
  32. }
  33. //if DebugEnabled {
  34. // println("UnmarshalBodyReusable request body:", string(requestBody))
  35. //}
  36. contentType := c.Request.Header.Get("Content-Type")
  37. if strings.HasPrefix(contentType, "application/json") {
  38. err = Unmarshal(requestBody, &v)
  39. } else if strings.Contains(contentType, gin.MIMEPOSTForm) {
  40. err = parseFormData(requestBody, &v)
  41. } else if strings.Contains(contentType, gin.MIMEMultipartPOSTForm) {
  42. err = parseMultipartFormData(c, requestBody, &v)
  43. } else {
  44. // skip for now
  45. // TODO: someday non json request have variant model, we will need to implementation this
  46. }
  47. if err != nil {
  48. return err
  49. }
  50. // Reset request body
  51. c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
  52. return nil
  53. }
  54. func SetContextKey(c *gin.Context, key constant.ContextKey, value any) {
  55. c.Set(string(key), value)
  56. }
  57. func GetContextKey(c *gin.Context, key constant.ContextKey) (any, bool) {
  58. return c.Get(string(key))
  59. }
  60. func GetContextKeyString(c *gin.Context, key constant.ContextKey) string {
  61. return c.GetString(string(key))
  62. }
  63. func GetContextKeyInt(c *gin.Context, key constant.ContextKey) int {
  64. return c.GetInt(string(key))
  65. }
  66. func GetContextKeyBool(c *gin.Context, key constant.ContextKey) bool {
  67. return c.GetBool(string(key))
  68. }
  69. func GetContextKeyStringSlice(c *gin.Context, key constant.ContextKey) []string {
  70. return c.GetStringSlice(string(key))
  71. }
  72. func GetContextKeyStringMap(c *gin.Context, key constant.ContextKey) map[string]any {
  73. return c.GetStringMap(string(key))
  74. }
  75. func GetContextKeyTime(c *gin.Context, key constant.ContextKey) time.Time {
  76. return c.GetTime(string(key))
  77. }
  78. func GetContextKeyType[T any](c *gin.Context, key constant.ContextKey) (T, bool) {
  79. if value, ok := c.Get(string(key)); ok {
  80. if v, ok := value.(T); ok {
  81. return v, true
  82. }
  83. }
  84. var t T
  85. return t, false
  86. }
  87. func ApiError(c *gin.Context, err error) {
  88. c.JSON(http.StatusOK, gin.H{
  89. "success": false,
  90. "message": err.Error(),
  91. })
  92. }
  93. func ApiErrorMsg(c *gin.Context, msg string) {
  94. c.JSON(http.StatusOK, gin.H{
  95. "success": false,
  96. "message": msg,
  97. })
  98. }
  99. func ApiSuccess(c *gin.Context, data any) {
  100. c.JSON(http.StatusOK, gin.H{
  101. "success": true,
  102. "message": "",
  103. "data": data,
  104. })
  105. }
  106. func ParseMultipartFormReusable(c *gin.Context) (*multipart.Form, error) {
  107. requestBody, err := GetRequestBody(c)
  108. if err != nil {
  109. return nil, err
  110. }
  111. contentType := c.Request.Header.Get("Content-Type")
  112. boundary := ""
  113. if idx := strings.Index(contentType, "boundary="); idx != -1 {
  114. boundary = contentType[idx+9:]
  115. }
  116. reader := multipart.NewReader(bytes.NewReader(requestBody), boundary)
  117. form, err := reader.ReadForm(32 << 20) // 32 MB max memory
  118. if err != nil {
  119. return nil, err
  120. }
  121. // Reset request body
  122. c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
  123. return form, nil
  124. }
  125. func parseFormData(data []byte, v any) error {
  126. values, err := url.ParseQuery(string(data))
  127. if err != nil {
  128. return err
  129. }
  130. formMap := make(map[string]any)
  131. for key, vals := range values {
  132. if len(vals) == 1 {
  133. formMap[key] = vals[0]
  134. } else {
  135. formMap[key] = vals
  136. }
  137. }
  138. jsonData, err := json.Marshal(formMap)
  139. if err != nil {
  140. return err
  141. }
  142. return Unmarshal(jsonData, v)
  143. }
  144. func parseMultipartFormData(c *gin.Context, data []byte, v any) error {
  145. contentType := c.Request.Header.Get("Content-Type")
  146. boundary := ""
  147. if idx := strings.Index(contentType, "boundary="); idx != -1 {
  148. boundary = contentType[idx+9:]
  149. }
  150. if boundary == "" {
  151. return Unmarshal(data, v) // Fallback to JSON
  152. }
  153. reader := multipart.NewReader(bytes.NewReader(data), boundary)
  154. form, err := reader.ReadForm(32 << 20) // 32 MB max memory
  155. if err != nil {
  156. return err
  157. }
  158. defer form.RemoveAll()
  159. formMap := make(map[string]any)
  160. for key, vals := range form.Value {
  161. if len(vals) == 1 {
  162. formMap[key] = vals[0]
  163. } else {
  164. formMap[key] = vals
  165. }
  166. }
  167. jsonData, err := Marshal(formMap)
  168. if err != nil {
  169. return err
  170. }
  171. return Unmarshal(jsonData, v)
  172. }