Gin error handler that responds with proper error responses when an error is added to the context.
				https://pkg.go.dev/codeberg.org/danjones000/gin-error-handler
			
		|  | ||
|---|---|---|
| .gitignore | ||
| CHANGELOG.md | ||
| go.mod | ||
| go.sum | ||
| handler.go | ||
| handler_test.go | ||
| int_test.go | ||
| LICENSE | ||
| middleware.go | ||
| middleware_test.go | ||
| options.go | ||
| options_test.go | ||
| README.md | ||
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.