2.2 KiB
2.2 KiB
Gin Error Handler
A Gin middleware and wrapper functions to make handling errors easier.
Installation
Use the module in the usual way: codeberg.org/danjones000/gin-error-handler.
Usage
package main
import (
"net/http"
handler "codeberg.org/danjones000/gin-error-handler"
rErrors "codeberg.org/danjones000/responsable-errors"
"github.com/go-playground/validator/v10"
"github.com/gin-gonic/gin"
)
var _ rErrors.ResponsableError = new(vError)
type vError struct {
validator.ValidationErrors
}
func (ve *vError) Msg() string {
return "Validation Error"
}
func (ve *vError) Status() int {
return http.StatusBadRequest
}
func (ve *vError) JSON() any {
errs := make([]map[string]string, len(ve))
for i, fe := range ve {
errs[i] = map[string]string{"field":fe.Field(),"error":fe.Error()}
}
return map[string][]map[string]string{"errors":errs}
}
func (ve *vError) MarshalJSON() ([]byte, error) {
return json.Marshal(e.JSON())
}
func (ve *vError) Unwrap() error {
return ve.ValidationErrors
}
func main() {
r := gin.New()
r.Use(handler.ErrorMiddleware(
handler.WithTransformer(func (err error) rErrors.ResponsableError {
var ve validator.ValidationErrors
if !errors.As(err, &ve) {
return nil
}
return &vError{ve}
}),
handler.WithDefaultTransformer(),
handler.WithLogger(ctx context.Context, err rErrors.ResponsableError) {
log.Print(err)
})
r.GET("/user", handler.HandlerWithErrorWrapper(func (c *gin.Context) error {
var qu struct {
id int `binding:"required"`
}{}
if err := c.ShouldBindQuery(&qu); err != nil {
return err
}
user, err := user.Get(qu.id)
if err != nil {
return err
}
if user == nil {
return rErrors.NewNotFound("User not found")
}
c.JSON(200, user)
}))
}
In our example, if ShouldBindQuery fails validation, we'll return a nicely formatted error with each validation error, due to our custom transformer. If no user is found, we'll return a 404, with an error message. And any errors are logged to stdout.