api.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package api
  2. import (
  3. "errors"
  4. "github.com/0xJacky/Nginx-UI/internal/logger"
  5. "github.com/gin-gonic/gin"
  6. val "github.com/go-playground/validator/v10"
  7. "net/http"
  8. "reflect"
  9. "strings"
  10. )
  11. func ErrHandler(c *gin.Context, err error) {
  12. logger.GetLogger().Errorln(err)
  13. c.JSON(http.StatusInternalServerError, gin.H{
  14. "message": err.Error(),
  15. })
  16. }
  17. type ValidError struct {
  18. Key string
  19. Message string
  20. }
  21. func BindAndValid(c *gin.Context, target interface{}) bool {
  22. err := c.ShouldBindJSON(target)
  23. if err != nil {
  24. logger.Error("bind err", err)
  25. var verrs val.ValidationErrors
  26. ok := errors.As(err, &verrs)
  27. if !ok {
  28. c.JSON(http.StatusNotAcceptable, gin.H{
  29. "message": "Requested with wrong parameters",
  30. "code": http.StatusNotAcceptable,
  31. })
  32. return false
  33. }
  34. t := reflect.TypeOf(target).Elem()
  35. errorsMap := make(map[string]interface{})
  36. for _, value := range verrs {
  37. var path []string
  38. namespace := strings.Split(value.StructNamespace(), ".")
  39. logger.Debug(t.Name(), namespace)
  40. if t.Name() != "" && len(namespace) > 1 {
  41. namespace = namespace[1:]
  42. }
  43. getJsonPath(t, namespace, &path)
  44. insertError(errorsMap, path, value.Tag())
  45. }
  46. c.JSON(http.StatusNotAcceptable, gin.H{
  47. "errors": errorsMap,
  48. "message": "Requested with wrong parameters",
  49. "code": http.StatusNotAcceptable,
  50. })
  51. return false
  52. }
  53. return true
  54. }
  55. // findField recursively finds the field in a nested struct
  56. func getJsonPath(t reflect.Type, fields []string, path *[]string) {
  57. f, ok := t.FieldByName(fields[0])
  58. if !ok {
  59. return
  60. }
  61. *path = append(*path, f.Tag.Get("json"))
  62. if len(fields) > 1 {
  63. subFields := fields[1:]
  64. getJsonPath(f.Type, subFields, path)
  65. }
  66. }
  67. // insertError inserts an error into the errors map
  68. func insertError(errorsMap map[string]interface{}, path []string, errorTag string) {
  69. if len(path) == 0 {
  70. return
  71. }
  72. jsonTag := path[0]
  73. if len(path) == 1 {
  74. // Last element in the path, set the error
  75. errorsMap[jsonTag] = errorTag
  76. return
  77. }
  78. // Create a new map if necessary
  79. if _, ok := errorsMap[jsonTag]; !ok {
  80. errorsMap[jsonTag] = make(map[string]interface{})
  81. }
  82. // Recursively insert into the nested map
  83. subMap, _ := errorsMap[jsonTag].(map[string]interface{})
  84. insertError(subMap, path[1:], errorTag)
  85. }