| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- package middleware
- import (
- "errors"
- "net/http"
- "reflect"
- "strings"
- "github.com/gin-gonic/gin"
- "github.com/gin-gonic/gin/binding"
- "github.com/go-playground/validator/v10"
- "github.com/mhsanaei/3x-ui/v3/web/entity"
- )
- var validate = validator.New(validator.WithRequiredStructEnabled())
- func BindAndValidate[T any](c *gin.Context) (*T, bool) {
- var dst T
- if err := c.ShouldBind(&dst); err != nil {
- writeBindFailure(c, err)
- return nil, false
- }
- if err := validate.Struct(&dst); err != nil {
- writeBindFailure(c, err)
- return nil, false
- }
- return &dst, true
- }
- func BindAndValidateInto(c *gin.Context, dst any) bool {
- if err := c.ShouldBind(dst); err != nil {
- writeBindFailure(c, err)
- return false
- }
- if err := validate.Struct(dst); err != nil {
- writeBindFailure(c, err)
- return false
- }
- return true
- }
- func BindJSONAndValidate[T any](c *gin.Context) (*T, bool) {
- var dst T
- if err := c.ShouldBindWith(&dst, binding.JSON); err != nil {
- writeBindFailure(c, err)
- return nil, false
- }
- if err := validate.Struct(&dst); err != nil {
- writeBindFailure(c, err)
- return nil, false
- }
- return &dst, true
- }
- func BindJSONAndValidateInto(c *gin.Context, dst any) bool {
- if err := c.ShouldBindWith(dst, binding.JSON); err != nil {
- writeBindFailure(c, err)
- return false
- }
- if err := validate.Struct(dst); err != nil {
- writeBindFailure(c, err)
- return false
- }
- return true
- }
- type FieldIssue struct {
- Field string `json:"field"`
- Rule string `json:"rule"`
- Param string `json:"param,omitempty"`
- Message string `json:"message"`
- }
- type ValidationPayload struct {
- Issues []FieldIssue `json:"issues"`
- Message string `json:"message"`
- }
- func writeBindFailure(c *gin.Context, err error) {
- payload := ValidationPayload{Issues: []FieldIssue{}, Message: err.Error()}
- var ve validator.ValidationErrors
- if errors.As(err, &ve) {
- payload.Issues = make([]FieldIssue, 0, len(ve))
- for _, fe := range ve {
- payload.Issues = append(payload.Issues, FieldIssue{
- Field: fe.Field(),
- Rule: fe.Tag(),
- Param: fe.Param(),
- Message: fe.Error(),
- })
- }
- }
- c.AbortWithStatusJSON(http.StatusOK, entity.Msg{
- Success: false,
- Msg: "request body failed validation",
- Obj: payload,
- })
- }
- func init() {
- validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
- name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
- if name == "-" || name == "" {
- return fld.Name
- }
- return name
- })
- }
|