From 7a9e5112eaaea58d55f181d3e5296e4ff839921c Mon Sep 17 00:00:00 2001 From: jloup Date: Wed, 14 Feb 2018 14:19:09 +0100 Subject: initial commit --- api/api.go | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 api/api.go (limited to 'api/api.go') diff --git a/api/api.go b/api/api.go new file mode 100644 index 0000000..7b7be49 --- /dev/null +++ b/api/api.go @@ -0,0 +1,130 @@ +package api + +import ( + "net/http" + "unicode" + + "github.com/gin-gonic/gin" +) + +type Error struct { + Code ErrorCode + UserMessage string + err error +} + +func (e Error) Err() error { + if e.err != nil { + return e + } + + return nil +} + +func (e Error) Error() string { + if e.err != nil { + return e.err.Error() + } + + return "" +} + +func NewInternalError(err error) *Error { + return &Error{InternalError, "internal error", err} +} + +func ToSnake(in string) string { + runes := []rune(in) + length := len(runes) + + var out []rune + for i := 0; i < length; i++ { + if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) { + out = append(out, '_') + } + out = append(out, unicode.ToLower(runes[i])) + } + + return string(out) +} + +type Response struct { + StatusCode Status `json:"-"` + ErrorCode ErrorCode `json:"-"` + + Status string `json:"status"` + Code string `json:"code,omitempty"` + Response interface{} `json:"response,omitempty"` + Message string `json:"message,omitempty"` +} + +func (r Response) populateStatus() Response { + r.Status = ToSnake(r.StatusCode.String()) + + if r.ErrorCode != 0 { + r.Code = ToSnake(r.ErrorCode.String()) + } + + return r +} + +func ErrorResponse(code ErrorCode, message string) Response { + return Response{ + StatusCode: NOK, + ErrorCode: code, + Message: message, + } +} + +func SuccessResponse(data interface{}) Response { + return Response{ + StatusCode: OK, + Response: data, + } +} + +func WriteJsonResponse(response Response, c *gin.Context) { + response = response.populateStatus() + + c.JSON(StatusToHttpCode(response.StatusCode, response.ErrorCode), response) +} + +func WriteBinary(contentType string, b []byte, c *gin.Context) { + c.Data(http.StatusOK, contentType, b) +} + +type Middleware func(*gin.Context) *Error + +func M(handler Middleware) gin.HandlerFunc { + return func(c *gin.Context) { + err := handler(c) + + if err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + c.Abort() + } else { + c.Next() + } + } +} + +type Query interface { + ValidateParams() *Error + Run() (interface{}, *Error) +} + +func RunQuery(query Query, c *gin.Context) { + if err := query.ValidateParams(); err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + return + } + + if out, err := query.Run(); err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + } else { + WriteJsonResponse(SuccessResponse(out), c) + } +} -- cgit v1.2.3