From b9ca0e081f232a3831318ab2424d2d2c68eeff21 Mon Sep 17 00:00:00 2001 From: Kai-Chu Chung Date: Wed, 11 Apr 2018 16:51:29 +0800 Subject: [PATCH] feat(gctx): add gctx for Google JSON style response (#5) --- ctx.go | 47 -------------------- ctx_test.go | 11 ++++- gctx.go | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ gerr.go | 6 ++- 4 files changed, 135 insertions(+), 50 deletions(-) create mode 100644 gctx.go diff --git a/ctx.go b/ctx.go index 3b2c74d..fb216aa 100644 --- a/ctx.go +++ b/ctx.go @@ -2,8 +2,6 @@ package ctx import ( "encoding/json" - "fmt" - "strconv" "strings" "github.com/labstack/echo" @@ -133,48 +131,3 @@ func (r *errorCall) Do() (err error) { } return r.c.JSONBlob(r.httpStatus, b) } - -// Google JSON Style error call -type gerrorCall struct { - c echo.Context - httpStatus int - responseParams GErrorResponse -} - -type gerrorMessage struct { - Code int `json:"code"` - Message string `json:"message"` - Errors []GError `json:"errors,omitempty"` -} - -type GErrorResponse struct { - ApiVersion string `json:"apiVersion"` - Error gerrorMessage `json:"error"` -} - -func (c CustomCtx) GError(errs ...GError) *gerrorCall { - rs := &gerrorCall{ - c: echo.Context(c), - responseParams: GErrorResponse{ - ApiVersion: apiVersion, - Error: gerrorMessage{}, - }, - } - - if len(errs) > 0 { - s, _ := strconv.Atoi(fmt.Sprintf("%d", errs[0].Code)[:3]) - rs.httpStatus = s - 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) - if err != nil { - return err - } - return r.c.JSONBlob(r.httpStatus, b) -} diff --git a/ctx_test.go b/ctx_test.go index 129d3a1..74230be 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -25,11 +25,18 @@ func TestCustomCtx(t *testing.T) { }, wantJSON: `{"apiVersion": "1.0", "data": "hello world"}`, }, + { + name: "200 with google json style", + givenHandler: func(c echo.Context) error { + return c.(ctx.CustomCtx).GResp(http.StatusOK).Data("hello world").Do() + }, + wantJSON: `{"apiVersion": "1.0", "data": "hello world"}`, + }, { name: "400 with google json style", givenHandler: func(c echo.Context) error { - gerr := ctx.NewGErrors().Append(ctx.GError{ + gerrs := ctx.NewGErrors().Append(ctx.GError{ Code: 40000001, Domain: "Calendar", Reason: "ResourceNotFoundException", @@ -47,7 +54,7 @@ func TestCustomCtx(t *testing.T) { Location: "part", }) - return c.(ctx.CustomCtx).GError(gerr...).Do() + return c.(ctx.CustomCtx).GResp().Errors(gerrs...).Do() }, 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"}]}}`, }, diff --git a/gctx.go b/gctx.go new file mode 100644 index 0000000..dc773d3 --- /dev/null +++ b/gctx.go @@ -0,0 +1,121 @@ +package ctx + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/labstack/echo" +) + +type grespCall struct { + ver string + c echo.Context + httpStatus []int +} + +func (c CustomCtx) GResp(httpStatus ...int) *grespCall { + rs := &grespCall{ + ver: apiVersion, + c: echo.Context(c), + httpStatus: httpStatus, + } + return rs +} + +type gdataCall struct { + c echo.Context + httpStatus int + responseParams SuccessResp +} + +func (r *grespCall) Ver(ver string) *grespCall { + r.ver = ver + return r +} + +func (r *grespCall) Data(data ...interface{}) *gdataCall { + var d interface{} + if len(data) == 0 { + d = []string{} + } else { + d = data[0] + } + + rs := &gdataCall{ + c: r.c, + httpStatus: r.httpStatus[0], + responseParams: SuccessResp{ + ApiVersion: r.ver, + Data: d, + }, + } + return rs +} + +// 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) { + b, err := json.Marshal(r.responseParams) + if err != nil { + return err + } + data := string(b) + for _, value := range replace { + data = value.Replace(data) + } + + return r.c.JSONBlob(r.httpStatus, []byte(data)) +} + +// Google JSON Style error call +type gerrorCall struct { + c echo.Context + httpStatus int + responseParams GErrorResponse +} + +type gerrorMessage 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"` +} + +func (r *grespCall) Errors(errs ...GError) *gerrorCall { + rs := &gerrorCall{ + c: r.c, + responseParams: GErrorResponse{ + ApiVersion: apiVersion, + Error: gerrorMessage{}, + }, + } + + if len(errs) > 0 { + if len(r.httpStatus) > 0 { + rs.httpStatus = r.httpStatus[0] + } else { + s, _ := strconv.Atoi(fmt.Sprintf("%d", errs[0].Code)[:3]) + rs.httpStatus = s + } + + 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) + if err != nil { + return err + } + return r.c.JSONBlob(r.httpStatus, b) +} diff --git a/gerr.go b/gerr.go index 69448ba..37db11f 100644 --- a/gerr.go +++ b/gerr.go @@ -3,7 +3,7 @@ package ctx type GErrors []GError type GError struct { - Code int `json:"-"` + Code uint `json:"-"` Domain string `json:"domain,omitempty"` Reason string `json:"reason,omitempty"` Message string `json:"message,omitempty"` @@ -18,4 +18,8 @@ func (c GErrors) Append(gerr GError) GErrors { return c } +func (c GErrors) Empty() bool { + return len(c) == 0 +} + func NewGErrors() GErrors { return GErrors{} }