diff --git a/context.go b/context.go index 216cecae..41e643af 100644 --- a/context.go +++ b/context.go @@ -199,9 +199,10 @@ func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{}) { // AbortWithError calls `AbortWithStatus()` and `Error()` internally. // This method stops the chain, writes the status code and pushes the specified error to `c.Errors`. // See Context.Error() for more details. -func (c *Context) AbortWithError(code int, err error) *Error { +func (c *Context) AbortWithError(code int, err error) { c.AbortWithStatus(code) - return c.Error(err) + c.Error(err) + return } /************************************/ @@ -212,10 +213,10 @@ func (c *Context) AbortWithError(code int, err error) *Error { // It's a good idea to call Error for each error that occurred during the resolution of a request. // A middleware can be used to collect all the errors and push them to a database together, // print a log, or append it in the HTTP response. -// Error will panic if err is nil. -func (c *Context) Error(err error) *Error { +// Error will ignore if err is nil. +func (c *Context) Error(err error) { if err == nil { - panic("err is nil") + return } parsedError, ok := err.(*Error) @@ -227,7 +228,30 @@ func (c *Context) Error(err error) *Error { } c.Errors = append(c.Errors, parsedError) - return parsedError + return +} + +// ErrorBindType attaches an error to the current context with specific ErrorType. The error is pushed to a list of errors. +// It's a good idea to call Error for each error that occurred during the resolution of a request. +// A middleware can be used to collect all the errors and push them to a database together, +// print a log, or append it in the HTTP response. +func (c *Context) ErrorBindType(err error, typ ErrorType) { + if err == nil { + return + } + + parsedError, ok := err.(*Error) + if !ok { + parsedError = &Error{ + Err: err, + Type: typ, + } + } else { + parsedError.SetType(typ) + } + + c.Errors = append(c.Errors, parsedError) + return } /************************************/ @@ -633,7 +657,7 @@ func (c *Context) BindHeader(obj interface{}) error { // It will abort the request with HTTP 400 if any error occurs. func (c *Context) BindUri(obj interface{}) error { if err := c.ShouldBindUri(obj); err != nil { - c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck + c.AbortWithError(http.StatusBadRequest, WrapError(err).SetType(ErrorTypeBind)) // nolint: errcheck return err } return nil @@ -644,7 +668,7 @@ func (c *Context) BindUri(obj interface{}) error { // See the binding package. func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { if err := c.ShouldBindWith(obj, b); err != nil { - c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck + c.AbortWithError(http.StatusBadRequest, WrapError(err).SetType(ErrorTypeBind)) // nolint: errcheck return err } return nil diff --git a/context_test.go b/context_test.go index e2f8de06..9be3a607 100644 --- a/context_test.go +++ b/context_test.go @@ -1354,19 +1354,12 @@ func TestContextError(t *testing.T) { assert.Equal(t, ErrorTypePublic, c.Errors[1].Type) assert.Equal(t, c.Errors.Last(), c.Errors[1]) - - defer func() { - if recover() == nil { - t.Error("didn't panic") - } - }() - c.Error(nil) // nolint: errcheck } func TestContextTypedError(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) - c.Error(errors.New("externo 0")).SetType(ErrorTypePublic) // nolint: errcheck - c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck + c.ErrorBindType(errors.New("externo 0"), ErrorTypePublic) + c.ErrorBindType(errors.New("interno 0"), ErrorTypePrivate) for _, err := range c.Errors.ByType(ErrorTypePublic) { assert.Equal(t, ErrorTypePublic, err.Type) @@ -1381,7 +1374,8 @@ func TestContextAbortWithError(t *testing.T) { w := httptest.NewRecorder() c, _ := CreateTestContext(w) - c.AbortWithError(http.StatusUnauthorized, errors.New("bad input")).SetMeta("some input") // nolint: errcheck + err := WrapError(errors.New("bad input")).SetMeta("some input") + c.AbortWithError(http.StatusUnauthorized, err) // nolint: errcheck assert.Equal(t, http.StatusUnauthorized, w.Code) assert.Equal(t, abortIndex, c.index) diff --git a/errors.go b/errors.go index 9a317992..4f7e4a36 100644 --- a/errors.go +++ b/errors.go @@ -41,6 +41,13 @@ type errorMsgs []*Error var _ error = &Error{} +// WrapError return Error wraps original error. +func WrapError(err error) *Error { + return &Error{ + Err: err, + } +} + // SetType sets the error's type. func (msg *Error) SetType(flags ErrorType) *Error { msg.Type = flags