Gin: 400 (Bad Request) gets automatically send when c.BindJSON(&struct) gets error

Created on 2 Jan 2017  路  2Comments  路  Source: gin-gonic/gin

Hi, i'm learning Gin and Go and thought i might get some insight from you guys.

I can't understand why Gin automatically sends an error 400 "Bad request" response when i try to bind and validate the incoming data from the a ajax request.

I set up a simple struct and set the "binding" to "required" on the Name field so it can be validated server-side :

type MyForm struct {
    Name string `json:"name"  binding:"required"
    OtherField string `json:"otherfield"`
}

func HandleARoute(c *gin.Context) {

    var form MyForm
    err := c.BindJSON(&form)

    if err == nil {

        // if the binding is successful  i save things to the database and return 
        // my custom JSON "success"  message - this works as long as the 
        // binding is successful

        c.JSON(http.StatusOK, gin.H{
            "status": "success",
            "msg":    "Great, it was saved",
        })

    } else {

        // THIS NEVER GETS SENT
        // if the binding fails (e.g. the required field was not provided or any 
        // other error occured) i want to send my custom message but can't 
        // because Gin has already sent its own response that  looks like this:
        //
        // {"msg":"Key: 'Stream.Name' Error:Field validation for 'Name' failed on the 'required' tag","status":"binding error"}

        c.JSON(http.StatusOK, gin.H{
            "status": "success",
            "msg":    "Great, it was saved",
        })
    }

}

So my question is, what is the right way to handle such errors so that i can send my own customized error message back to the browser ?

Most helpful comment

Temporary solution, create a new package, copy the BindWith and BindJSON func from gin, comment out c.AbortWithError(400, err).SetType(ErrorTypeBind) and use

package ginfix

import (
    "github.com/gin-gonic/gin/binding"
    "github.com/gin-gonic/gin"
)

// BindJSON is a shortcut for c.BindWith(obj, binding.JSON)
func BindJSON(obj interface{}, c *gin.Context) error {
    return BindWith(obj, binding.JSON, c)
}

// BindWith binds the passed struct pointer using the specified binding engine.
// See the binding package.
func BindWith(obj interface{}, b binding.Binding, c *gin.Context) error {
    if err := b.Bind(c.Request, obj); err != nil {
        //c.AbortWithError(400, err).SetType(ErrorTypeBind)
        return err
    }
    return nil
}

All 2 comments

Sorry i found this issue discussed here: https://github.com/gin-gonic/gin/issues/633

Temporary solution, create a new package, copy the BindWith and BindJSON func from gin, comment out c.AbortWithError(400, err).SetType(ErrorTypeBind) and use

package ginfix

import (
    "github.com/gin-gonic/gin/binding"
    "github.com/gin-gonic/gin"
)

// BindJSON is a shortcut for c.BindWith(obj, binding.JSON)
func BindJSON(obj interface{}, c *gin.Context) error {
    return BindWith(obj, binding.JSON, c)
}

// BindWith binds the passed struct pointer using the specified binding engine.
// See the binding package.
func BindWith(obj interface{}, b binding.Binding, c *gin.Context) error {
    if err := b.Bind(c.Request, obj); err != nil {
        //c.AbortWithError(400, err).SetType(ErrorTypeBind)
        return err
    }
    return nil
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mdnight picture mdnight  路  3Comments

xpbliss picture xpbliss  路  3Comments

nxvl picture nxvl  路  3Comments

oryband picture oryband  路  3Comments

mastrolinux picture mastrolinux  路  3Comments