Skip to content

Commit

Permalink
feat(errhandler):support custom http error handler
Browse files Browse the repository at this point in the history
  • Loading branch information
cutedogspark committed Apr 24, 2018
1 parent 3acd662 commit 0afcbaf
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 45 deletions.
38 changes: 31 additions & 7 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 20 additions & 3 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,27 @@
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
name = "github.com/labstack/echo"
version = "3.2.6"
version = "3.3.5"

[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.0"

[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"

[prune]
go-tests = true
unused-packages = true
14 changes: 7 additions & 7 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestCustomCtx(t *testing.T) {
{
name: "200 with google json style",
givenHandler: func(c echo.Context) error {
return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("hello world").Do()
return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("hello world").Out()
},
wantJSON: `{"apiVersion": "1.0", "data": "hello world"}`,
},
Expand All @@ -46,17 +46,17 @@ func TestCustomCtx(t *testing.T) {
ExtendedHelp: "http://help-link",
SendReport: "http://report.dajui.com/",
}).Append(&ctx.GError{
Code: 40000001,
Code: 40000002,
Domain: "global",
Reason: "required",
Message: "Required parameter: part",
LocationType: "parameter",
Location: "part",
})

return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Do()
return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Out()
},
wantJSON: `{"apiVersion":"1.0","error":{"code":40000001,"message":"Resources is not exist","errors":[{"extendedHelp":"http://help-link", "sendReport":"http://report.dajui.com/", "domain":"Calendar", "reason":"ResourceNotFoundException", "message":"Resources is not exist", "location":"query", "locationType":"database query"},{"message":"Required parameter: part", "location":"part", "locationType":"parameter", "domain":"global", "reason":"required"}]}}`,
wantJSON: `{"apiVersion":"1.0","error":{"code":40000001,"message":"Resources is not exist","errors":[{"code": 40000001, "extendedHelp":"http://help-link", "sendReport":"http://report.dajui.com/", "domain":"Calendar", "reason":"ResourceNotFoundException", "message":"Resources is not exist", "location":"query", "locationType":"database query"},{"code": 40000002, "message":"Required parameter: part", "location":"part", "locationType":"parameter", "domain":"global", "reason":"required"}]}}`,
},
{
name: "400 with string errors",
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestCustomCtx(t *testing.T) {
ExtendedHelp: "http://help-link",
SendReport: "http://report.dajui.com/",
}).Append(&ctx.GError{
Code: 40000001,
Code: 40000002,
Domain: "global",
Reason: "required",
Message: "Required parameter: part",
Expand All @@ -107,9 +107,9 @@ func TestCustomCtx(t *testing.T) {

gerrs.AppendDomain("handler")

return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Do()
return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Out()
},
wantJSON: `{"apiVersion":"1.0","error":{"code":40000001,"message":"Resources is not exist","errors":[{"extendedHelp":"http://help-link", "sendReport":"http://report.dajui.com/", "domain":"handler.Calendar", "reason":"ResourceNotFoundException", "message":"Resources is not exist", "location":"query", "locationType":"database query"},{"message":"Required parameter: part", "location":"part", "locationType":"parameter", "domain":"handler.global", "reason":"required"}]}}`,
wantJSON: `{"apiVersion":"1.0","error":{"code":40000001,"message":"Resources is not exist","errors":[{"code": 40000001, "extendedHelp":"http://help-link", "sendReport":"http://report.dajui.com/", "domain":"handler.Calendar", "reason":"ResourceNotFoundException", "message":"Resources is not exist", "location":"query", "locationType":"database query"},{"code": 40000002, "message":"Required parameter: part", "location":"part", "locationType":"parameter", "domain":"handler.global", "reason":"required"}]}}`,
},
}

Expand Down
89 changes: 89 additions & 0 deletions example/ErrorHandler/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"encoding/json"
"fmt"
"net/http"

"github.com/cutedogspark/echo-custom-context"
"github.com/labstack/echo"
"github.com/pkg/errors"
)

func HTTPErrorHandler(err error, c echo.Context) {
if he, ok := err.(*ctx.GErrCall); ok {
err = errors.WithStack(he)
b, _ := json.Marshal(he.ResponseParams)
c.JSONBlob(he.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{
Code: uint(he.Code),
Message: fmt.Sprintf("%+v", he.Message),
})
b, _ := json.Marshal(gErrs.ResponseParams)
c.JSONBlob(he.Code, b)
} else {
// define unknown error message
err = errors.New("unknown error")
gCtx := ctx.CustomCtx{}
gErrs := gCtx.GResp().Errors(&ctx.GError{
Code: http.StatusInternalServerError,
Message: err.Error(),
})
b, _ := json.Marshal(gErrs.ResponseParams)
c.JSONBlob(he.Code, b)
}
c.Logger().Error(err)
}

func main() {

e := echo.New()
e.HideBanner = true
e.HTTPErrorHandler = HTTPErrorHandler
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
return next(ctx.CustomCtx{c})
}
})

e.GET("/", func(c echo.Context) error {
// no use error handler function
return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("Service").Out()
})

e.GET("/gerr", func(c echo.Context) error {
gerrs := ctx.NewGErrors().Append(&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/",
}).Append(&ctx.GError{
Code: 40000002,
Domain: "global",
Reason: "required",
Message: "Required parameter: part",
LocationType: "parameter",
Location: "part",
})
return c.(ctx.CustomCtx).GResp().Errors(*gerrs...).Do()
})

e.GET("/echo-error", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "default echo error handler")
})

e.GET("/unknown-error", func(c echo.Context) error {
return errors.New("Goodbye")
})

// Start server
e.Logger.Fatal(e.Start(":1234"))
}
11 changes: 6 additions & 5 deletions example/GError/main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package main

import (
"net/http"

"github.com/cutedogspark/echo-custom-context"
"github.com/labstack/echo"
"net/http"
)

func main() {
Expand All @@ -18,7 +19,7 @@ func main() {
})

e.GET("/", func(c echo.Context) error {
return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("Service").Do()
return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("Service").Out()
})

e.GET("/error", func(c echo.Context) error {
Expand All @@ -29,7 +30,7 @@ func main() {
Message: "parameter required : id",
Location: "id",
LocationType: "parameter",
}).Do()
}).Out()
})

e.GET("/errors", func(c echo.Context) error {
Expand All @@ -52,10 +53,10 @@ func main() {

ctxErr.AppendDomain("handler")

return c.(ctx.CustomCtx).GResp().Errors(*ctxErr...).Do()
return c.(ctx.CustomCtx).GResp().Errors(*ctxErr...).Out()
})

// Start server
e.Logger.Fatal(e.Start(":1323"))
e.Logger.Fatal(e.Start(":1234"))

}
56 changes: 34 additions & 22 deletions gctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (r *grespCall) Data(data ...interface{}) *gdataCall {
// Response Json Format
// - replace string when response raw data
// - ex: replace := strings.NewReplacer("{PP_KEY}", encryptionKey)
func (r *gdataCall) Do(replace ...*strings.Replacer) (err error) {
func (r *gdataCall) Out(replace ...*strings.Replacer) (err error) {
b, err := json.Marshal(r.responseParams)
if err != nil {
return err
Expand All @@ -71,53 +71,65 @@ func (r *gdataCall) Do(replace ...*strings.Replacer) (err error) {
}

// Google JSON Style error call
type gerrorCall struct {
type GErrCall struct {
c echo.Context
httpStatus int
responseParams GErrorResponse
HttpStatus int
ResponseParams GErrResponse
}

type gerrorMessage struct {
type GErrMessage struct {
Code uint `json:"code"`
Message string `json:"message"`
Errors []*GError `json:"errors,omitempty"`
}

type GErrorResponse struct {
ApiVersion string `json:"apiVersion"`
Error gerrorMessage `json:"error"`
type GErrResponse struct {
ApiVersion string `json:"apiVersion"`
Error GErrMessage `json:"error"`
}

func (r *grespCall) Errors(errs ...*GError) *gerrorCall {
rs := &gerrorCall{
func (r *grespCall) Errors(errs ...*GError) *GErrCall {
rs := &GErrCall{
c: r.c,
responseParams: GErrorResponse{
ResponseParams: GErrResponse{
ApiVersion: apiVersion,
Error: gerrorMessage{},
Error: GErrMessage{},
},
}

if len(errs) > 0 {
if len(r.httpStatus) > 0 {
rs.httpStatus = r.httpStatus[0]
rs.HttpStatus = r.httpStatus[0]
} else {
s, _ := strconv.Atoi(fmt.Sprintf("%d", errs[0].Code)[:3])
rs.httpStatus = s
rs.HttpStatus = s
}

rs.responseParams.Error.Code = errs[0].Code
rs.responseParams.Error.Message = errs[0].Message
rs.responseParams.Error.Errors = errs

r.c.Set("gerrs", GErrors(errs))
rs.ResponseParams.Error.Code = errs[0].Code
rs.ResponseParams.Error.Message = errs[0].Message
rs.ResponseParams.Error.Errors = errs
}
return rs
}

func (r *gerrorCall) Do() (err error) {
b, err := json.Marshal(r.responseParams)
// Custom HTTP Error Handler
func (r *GErrCall) Do() (err error) {
return r
}

// Response Json Out
func (r *GErrCall) Out() (err error) {
b, err := json.Marshal(r.ResponseParams)
if err != nil {
return err
}
return r.c.JSONBlob(r.httpStatus, b)
return r.c.JSONBlob(r.HttpStatus, b)
}

func (r *GErrCall) Error() string {
b, err := json.Marshal(r.ResponseParams)
if err != nil {
return err.Error()
}
return string(b)
}
Loading

0 comments on commit 0afcbaf

Please sign in to comment.