2024-01-17 19:59:54 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# Gin Error Handler
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								A Gin middleware and wrapper functions to make handling errors easier.
							 
						 
					
						
							
								
									
										
										
										
											2024-01-22 22:20:04 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Installation
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Use the module in the usual way: `codeberg.org/danjones000/gin-error-handler` .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Usage
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```go
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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.