diff --git a/Gopkg.lock b/Gopkg.lock index f700e3c..612c039 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -7,6 +7,21 @@ revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" +[[projects]] + name = "github.com/go-playground/locales" + packages = [ + ".", + "currency" + ] + revision = "f63010822830b6fe52288ee52d5a1151088ce039" + version = "v0.12.1" + +[[projects]] + name = "github.com/go-playground/universal-translator" + packages = ["."] + revision = "b32fa301c9fe55953584134cb6853a13c87ec0a1" + version = "v0.16.0" + [[projects]] name = "github.com/labstack/echo" packages = ["."] @@ -79,9 +94,15 @@ packages = ["unix"] revision = "79b0c6888797020a994db17c8510466c72fe75d9" +[[projects]] + name = "gopkg.in/go-playground/validator.v9" + packages = ["."] + revision = "14984d91328f9612b58443cbdf4a077d4fd71091" + version = "v9.15.0" + [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "9270bbe8382ef12ba264cf489dede9949f81b909d34657daef325f4d7ab4bd8b" + inputs-digest = "14b12ad235bd54a2b6ab0160766d0b88ad9bed2c0b55355632e8b4aa56f18dc3" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index e5bb50a..c03c95a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -40,3 +40,7 @@ [prune] go-tests = true unused-packages = true + +[[constraint]] + name = "gopkg.in/go-playground/validator.v9" + version = "9.15.0" diff --git a/errhandler.go b/errhandler.go index c2fd649..696642d 100644 --- a/errhandler.go +++ b/errhandler.go @@ -1,40 +1,52 @@ package ctx import ( + "encoding/json" "fmt" "net/http" + "strings" "github.com/labstack/echo" + "github.com/pkg/errors" + "gopkg.in/go-playground/validator.v9" ) func HTTPErrorHandler(err error, c echo.Context) { - - r := CustomCtx{c} - code := http.StatusInternalServerError - var msg interface{} - if he, ok := err.(*echo.HTTPError); ok { - code = he.Code - msg = he.Message - } - if err := r.Resp(code).Error(fmt.Sprintf("%v", msg)).Code(code).Do(); err != nil { - c.Logger().Error(err) - } - - /* - errDate := sri.NewErrors() - errDate.Add(msg) - if err := r.Resp(code).Error(fmt.Sprintf("%v", msg)).Code(code).Errors(errDate.Error()).Do(); err != nil { - c.Logger().Error(err) + if he, ok := err.(*GErrCall); ok { + err = errors.WithStack(he) + b, _ := json.Marshal(he.ResponseParams) + c.JSONBlob(he.HttpStatus, b) + } else if he, ok := err.(*GError); ok { + err = errors.WithStack(he) + gErrs := CustomCtx{}.GResp().Errors(he) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) + } else if he, ok := err.(*echo.HTTPError); ok { + // warp echo error struct + err = errors.WithStack(he) + gErrs := CustomCtx{}.GResp().Errors(&GError{ + Code: uint(he.Code), + Message: fmt.Sprintf("%+v", he.Message), + }) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) + } else if _, ok := err.(*validator.InvalidValidationError); !ok { + var errMsg []string + for _, err := range err.(validator.ValidationErrors) { + errMsg = append(errMsg, fmt.Sprintf("%s:%s", err.Field(), err.ActualTag())) } - { - "apiVersion": "v1", - "error": { - "code": 404, - "message": "Not Found", - "errors": [ - "Not Found" - ] - } - } - */ + gErrs := CustomCtx{}.GResp(http.StatusBadRequest).Errors(&GError{Code: http.StatusBadRequest, Message: strings.Join(errMsg, ",")}) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) + } else { + // define unknown error message + err = errors.New("unknown error") + gErrs := CustomCtx{}.GResp().Errors(&GError{ + Code: http.StatusInternalServerError, + Message: err.Error(), + }) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) + } + c.Logger().Error(err) } diff --git a/example/ErrorHandler/main.go b/example/ErrorHandler/main.go index 18680c1..9ba1d1f 100644 --- a/example/ErrorHandler/main.go +++ b/example/ErrorHandler/main.go @@ -4,10 +4,12 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "github.com/cutedogspark/echo-custom-context" "github.com/labstack/echo" "github.com/pkg/errors" + "gopkg.in/go-playground/validator.v9" ) func HTTPErrorHandler(err error, c echo.Context) { @@ -15,34 +17,56 @@ func HTTPErrorHandler(err error, c echo.Context) { err = errors.WithStack(he) b, _ := json.Marshal(he.ResponseParams) c.JSONBlob(he.HttpStatus, b) + } else if he, ok := err.(*ctx.GError); ok { + err = errors.WithStack(he) + gErrs := ctx.CustomCtx{}.GResp().Errors(he) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) } else if he, ok := err.(*echo.HTTPError); ok { // warp echo error struct err = errors.WithStack(he) - gCtx := ctx.CustomCtx{} - gErrs := gCtx.GResp().Errors(&ctx.GError{ + gErrs := ctx.CustomCtx{}.GResp().Errors(&ctx.GError{ Code: uint(he.Code), Message: fmt.Sprintf("%+v", he.Message), }) b, _ := json.Marshal(gErrs.ResponseParams) - c.JSONBlob(he.Code, b) + c.JSONBlob(gErrs.HttpStatus, b) + } else if _, ok := err.(*validator.InvalidValidationError); !ok { + var errMsg []string + for _, err := range err.(validator.ValidationErrors) { + errMsg = append(errMsg, fmt.Sprintf("%s:%s", err.Field(), err.ActualTag())) + } + gErrs := ctx.CustomCtx{}.GResp(http.StatusBadRequest).Errors(&ctx.GError{Code: http.StatusBadRequest, Message: strings.Join(errMsg, ",")}) + b, _ := json.Marshal(gErrs.ResponseParams) + c.JSONBlob(gErrs.HttpStatus, b) } else { // define unknown error message err = errors.New("unknown error") - gCtx := ctx.CustomCtx{} - gErrs := gCtx.GResp().Errors(&ctx.GError{ + gErrs := ctx.CustomCtx{}.GResp().Errors(&ctx.GError{ Code: http.StatusInternalServerError, Message: err.Error(), }) b, _ := json.Marshal(gErrs.ResponseParams) - c.JSONBlob(he.Code, b) + c.JSONBlob(gErrs.HttpStatus, b) } c.Logger().Error(err) } +type ( + CustomValidator struct { + validator *validator.Validate + } +) + +func (cv *CustomValidator) Validate(i interface{}) error { + return cv.validator.Struct(i) +} + func main() { e := echo.New() e.HideBanner = true + e.Validator = &CustomValidator{validator: validator.New()} e.HTTPErrorHandler = HTTPErrorHandler e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { @@ -55,7 +79,7 @@ func main() { return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("Service").Out() }) - e.GET("/gerr", func(c echo.Context) error { + e.GET("/gerrs", func(c echo.Context) error { gerrs := ctx.NewGErrors().Append(&ctx.GError{ Code: 40000001, Domain: "Calendar", @@ -73,9 +97,24 @@ func main() { LocationType: "parameter", Location: "part", }) + return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Do() }) + e.GET("/gerr", func(c echo.Context) error { + gErr := &ctx.GError{ + Code: 40000001, + Domain: "Calendar", + Reason: "ResourceNotFoundException", + Message: "Resources is not exist", + LocationType: "database query", + Location: "query", + ExtendedHelp: "http://help-link", + SendReport: "http://report.dajui.com/", + } + return gErr + }) + e.GET("/echo-error", func(c echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, "default echo error handler") }) @@ -84,6 +123,22 @@ func main() { return errors.New("Goodbye") }) + e.GET("/validate-error", func(c echo.Context) error { + + type req struct { + App string `form:"app" validate:"required,numeric"` + Key string `form:"key" validate:"required"` + ClientId int `form:"clientid" validate:"required"` + } + in := new(req) + in.App = "God" + + if err := c.Validate(in); err != nil { + return err + } + return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("validate sucess").Out() + }) + // Start server e.Logger.Fatal(e.Start(":1234")) }