]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git/blob - api/api.go
initial commit
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git] / api / api.go
1 package api
2
3 import (
4 "net/http"
5 "unicode"
6
7 "github.com/gin-gonic/gin"
8 )
9
10 type Error struct {
11 Code ErrorCode
12 UserMessage string
13 err error
14 }
15
16 func (e Error) Err() error {
17 if e.err != nil {
18 return e
19 }
20
21 return nil
22 }
23
24 func (e Error) Error() string {
25 if e.err != nil {
26 return e.err.Error()
27 }
28
29 return ""
30 }
31
32 func NewInternalError(err error) *Error {
33 return &Error{InternalError, "internal error", err}
34 }
35
36 func ToSnake(in string) string {
37 runes := []rune(in)
38 length := len(runes)
39
40 var out []rune
41 for i := 0; i < length; i++ {
42 if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
43 out = append(out, '_')
44 }
45 out = append(out, unicode.ToLower(runes[i]))
46 }
47
48 return string(out)
49 }
50
51 type Response struct {
52 StatusCode Status `json:"-"`
53 ErrorCode ErrorCode `json:"-"`
54
55 Status string `json:"status"`
56 Code string `json:"code,omitempty"`
57 Response interface{} `json:"response,omitempty"`
58 Message string `json:"message,omitempty"`
59 }
60
61 func (r Response) populateStatus() Response {
62 r.Status = ToSnake(r.StatusCode.String())
63
64 if r.ErrorCode != 0 {
65 r.Code = ToSnake(r.ErrorCode.String())
66 }
67
68 return r
69 }
70
71 func ErrorResponse(code ErrorCode, message string) Response {
72 return Response{
73 StatusCode: NOK,
74 ErrorCode: code,
75 Message: message,
76 }
77 }
78
79 func SuccessResponse(data interface{}) Response {
80 return Response{
81 StatusCode: OK,
82 Response: data,
83 }
84 }
85
86 func WriteJsonResponse(response Response, c *gin.Context) {
87 response = response.populateStatus()
88
89 c.JSON(StatusToHttpCode(response.StatusCode, response.ErrorCode), response)
90 }
91
92 func WriteBinary(contentType string, b []byte, c *gin.Context) {
93 c.Data(http.StatusOK, contentType, b)
94 }
95
96 type Middleware func(*gin.Context) *Error
97
98 func M(handler Middleware) gin.HandlerFunc {
99 return func(c *gin.Context) {
100 err := handler(c)
101
102 if err != nil {
103 WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c)
104 c.Error(err)
105 c.Abort()
106 } else {
107 c.Next()
108 }
109 }
110 }
111
112 type Query interface {
113 ValidateParams() *Error
114 Run() (interface{}, *Error)
115 }
116
117 func RunQuery(query Query, c *gin.Context) {
118 if err := query.ValidateParams(); err != nil {
119 WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c)
120 c.Error(err)
121 return
122 }
123
124 if out, err := query.Run(); err != nil {
125 WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c)
126 c.Error(err)
127 } else {
128 WriteJsonResponse(SuccessResponse(out), c)
129 }
130 }