@@ -4,11 +4,28 @@ import (
44 "errors"
55 "github.com/0xJacky/Nginx-UI/internal/logger"
66 "github.com/gin-gonic/gin"
7+ "github.com/gin-gonic/gin/binding"
78 val "github.com/go-playground/validator/v10"
89 "net/http"
910 "reflect"
11+ "regexp"
12+ "strings"
1013)
1114
15+ func init () {
16+ if v , ok := binding .Validator .Engine ().(* val.Validate ); ok {
17+ err := v .RegisterValidation ("alphanumdash" , func (fl val.FieldLevel ) bool {
18+ return regexp .MustCompile (`^[a-zA-Z0-9-]+$` ).MatchString (fl .Field ().String ())
19+ })
20+
21+ if err != nil {
22+ logger .Fatal (err )
23+ }
24+ return
25+ }
26+ logger .Fatal ("binding validator engine is not initialized" )
27+ }
28+
1229func ErrHandler (c * gin.Context , err error ) {
1330 logger .GetLogger ().Errorln (err )
1431 c .JSON (http .StatusInternalServerError , gin.H {
@@ -22,7 +39,6 @@ type ValidError struct {
2239}
2340
2441func BindAndValid (c * gin.Context , target interface {}) bool {
25- errs := make (map [string ]string )
2642 err := c .ShouldBindJSON (target )
2743 if err != nil {
2844 logger .Error ("bind err" , err )
@@ -31,24 +47,23 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
3147 ok := errors .As (err , & verrs )
3248
3349 if ! ok {
34- logger .Error ("valid err" , verrs )
3550 c .JSON (http .StatusNotAcceptable , gin.H {
3651 "message" : "Requested with wrong parameters" ,
3752 "code" : http .StatusNotAcceptable ,
38- "error" : verrs ,
3953 })
4054 return false
4155 }
4256
57+ t := reflect .TypeOf (target ).Elem ()
58+ errorsMap := make (map [string ]interface {})
4359 for _ , value := range verrs {
44- t := reflect .ValueOf (target )
45- realType := t .Type ().Elem ()
46- field , _ := realType .FieldByName (value .StructField ())
47- errs [field .Tag .Get ("json" )] = value .Tag ()
60+ var path []string
61+ getJsonPath (t , value .StructNamespace (), & path )
62+ insertError (errorsMap , path , value .Tag ())
4863 }
4964
5065 c .JSON (http .StatusNotAcceptable , gin.H {
51- "errors" : errs ,
66+ "errors" : errorsMap ,
5267 "message" : "Requested with wrong parameters" ,
5368 "code" : http .StatusNotAcceptable ,
5469 })
@@ -58,3 +73,45 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
5873
5974 return true
6075}
76+
77+ // findField recursively finds the field in a nested struct
78+ func getJsonPath (t reflect.Type , namespace string , path * []string ) {
79+ fields := strings .Split (namespace , "." )
80+ if len (fields ) == 0 {
81+ return
82+ }
83+ f , ok := t .FieldByName (fields [0 ])
84+ if ! ok {
85+ return
86+ }
87+
88+ * path = append (* path , f .Tag .Get ("json" ))
89+
90+ if len (fields ) > 1 {
91+ subFields := strings .Join (fields [1 :], "." )
92+ getJsonPath (f .Type , subFields , path )
93+ }
94+ }
95+
96+ // insertError inserts an error into the errors map
97+ func insertError (errorsMap map [string ]interface {}, path []string , errorTag string ) {
98+ if len (path ) == 0 {
99+ return
100+ }
101+
102+ jsonTag := path [0 ]
103+ if len (path ) == 1 {
104+ // Last element in the path, set the error
105+ errorsMap [jsonTag ] = errorTag
106+ return
107+ }
108+
109+ // Create a new map if necessary
110+ if _ , ok := errorsMap [jsonTag ]; ! ok {
111+ errorsMap [jsonTag ] = make (map [string ]interface {})
112+ }
113+
114+ // Recursively insert into the nested map
115+ subMap , _ := errorsMap [jsonTag ].(map [string ]interface {})
116+ insertError (subMap , path [1 :], errorTag )
117+ }
0 commit comments