gin.go 4.6 KB

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