Search code examples
gogo-gin

HTTP Request Validation Middleware In Go


I am trying to create a common HTTP request validator middleware function that accepts type (maybe reflect.Type) as an argument and then using the package github.com/go-playground/validator/v10 to be able to unmarshall JSON into struct of mentioned type and validate the struct. I've tried to explain with the following example code...

EXAMPLE

type LoginRequestBody struct {
   Username string `json:"username",validate:"required"`
   Password string `json:"password",validate:"required"`
}

type SignupReqBody struct {
   Username string `json:"username",validate:"required"`
   Password string `json:"password",validate:"required"`
   Age      int    `json:"age",validate:"required"`
}

// sample routers with a common middleware validator function
router.POST("/login", ReqValidate("LoginRequestBody"), LoginController)
router.POST("/signup", ReqValidate("SignupReqBody"), SignupController)

func ReqValidate(<something>) gin.HandlerFunc {
   return func (c *gin.Context) {
      // unmarshalling JSON into a struct
      // common validation logic...
      c.Next()
   }
}

Overall, i wanna achieve the same validator flexibility as there in Node.js using Joi package.


Solution

  • I don't know if it is necessary to use middleware but I was recently trying to do something and I found an excellent tutorial that you can see here.

    With Gin You can use binding:

    Example:

    package main
    import (
      "github.com/gin-gonic/gin"
      "net/http"
    )
    type AnyStruct struct {
       Price uint `json:"price" binding:"required,gte=10,lte=1000"`
    }
    func main() {
      engine:=gin.New()
      engine.POST("/test", func(context *gin.Context) {
         body:=AnyStruct{}
         if err:=context.ShouldBindJSON(&body);err!=nil{
            context.AbortWithStatusJSON(http.StatusBadRequest,
            gin.H{
                "error": "VALIDATEERR-1",
                "message": "Invalid inputs. Please check your inputs"})
            return
         }
         context.JSON(http.StatusAccepted,&body)
      })
      engine.Run(":3000")
    }