friendly error handling

due to c.Error() is not friendly to golint and useless returned,
thought to remove it.
This commit is contained in:
LiangXianSen 2020-09-04 17:27:41 +08:00
parent b860d8672d
commit 29568a5ecf
3 changed files with 43 additions and 18 deletions

View File

@ -199,9 +199,10 @@ func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{}) {
// AbortWithError calls `AbortWithStatus()` and `Error()` internally. // AbortWithError calls `AbortWithStatus()` and `Error()` internally.
// This method stops the chain, writes the status code and pushes the specified error to `c.Errors`. // This method stops the chain, writes the status code and pushes the specified error to `c.Errors`.
// See Context.Error() for more details. // 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) 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. // 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, // 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. // print a log, or append it in the HTTP response.
// Error will panic if err is nil. // Error will ignore if err is nil.
func (c *Context) Error(err error) *Error { func (c *Context) Error(err error) {
if err == nil { if err == nil {
panic("err is nil") return
} }
parsedError, ok := err.(*Error) parsedError, ok := err.(*Error)
@ -227,7 +228,30 @@ func (c *Context) Error(err error) *Error {
} }
c.Errors = append(c.Errors, parsedError) 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. // It will abort the request with HTTP 400 if any error occurs.
func (c *Context) BindUri(obj interface{}) error { func (c *Context) BindUri(obj interface{}) error {
if err := c.ShouldBindUri(obj); err != nil { 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 err
} }
return nil return nil
@ -644,7 +668,7 @@ func (c *Context) BindUri(obj interface{}) error {
// See the binding package. // See the binding package.
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error {
if err := c.ShouldBindWith(obj, b); err != nil { 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 err
} }
return nil return nil

View File

@ -1354,19 +1354,12 @@ func TestContextError(t *testing.T) {
assert.Equal(t, ErrorTypePublic, c.Errors[1].Type) assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
assert.Equal(t, c.Errors.Last(), c.Errors[1]) 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) { func TestContextTypedError(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Error(errors.New("externo 0")).SetType(ErrorTypePublic) // nolint: errcheck c.ErrorBindType(errors.New("externo 0"), ErrorTypePublic)
c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck c.ErrorBindType(errors.New("interno 0"), ErrorTypePrivate)
for _, err := range c.Errors.ByType(ErrorTypePublic) { for _, err := range c.Errors.ByType(ErrorTypePublic) {
assert.Equal(t, ErrorTypePublic, err.Type) assert.Equal(t, ErrorTypePublic, err.Type)
@ -1381,7 +1374,8 @@ func TestContextAbortWithError(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
c, _ := CreateTestContext(w) 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, http.StatusUnauthorized, w.Code)
assert.Equal(t, abortIndex, c.index) assert.Equal(t, abortIndex, c.index)

View File

@ -41,6 +41,13 @@ type errorMsgs []*Error
var _ error = &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. // SetType sets the error's type.
func (msg *Error) SetType(flags ErrorType) *Error { func (msg *Error) SetType(flags ErrorType) *Error {
msg.Type = flags msg.Type = flags