forked from azurity/go-dogma
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandle.go
115 lines (107 loc) · 2.29 KB
/
handle.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package dogma
import (
"encoding/json"
"fmt"
"github.com/labstack/echo/v4"
"log"
"net/http"
"reflect"
)
type Context = echo.Context
type Method struct {
Name string `json:"name"`
Method string `json:"method"`
}
type Server struct {
router *echo.Group
desc map[reflect.Type]Method
logger *log.Logger
}
func New(router *echo.Group, desc map[reflect.Type]Method, logger *log.Logger) *Server {
return &Server{
router: router,
desc: desc,
logger: logger,
}
}
func typedParse[T any](data []byte) (*T, error) {
ret := new(T)
err := json.Unmarshal(data, ret)
if err != nil {
return nil, err
}
return ret, nil
}
type ResultBase struct {
Message string `json:"message"`
}
func HandleRestFunc[T func(Context, PU, PC) (R, error), PU any, PC any, R any](s *Server, handle T) {
typ := reflect.TypeOf(new(T))
desc, ok := s.desc[typ]
if !ok {
log.Panicln(fmt.Sprintf("no such api for type: %s", typ.String()))
}
var fn func(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route = nil
switch desc.Method {
case "GET":
fn = s.router.GET
break
case "POST":
fn = s.router.POST
break
case "PUT":
fn = s.router.PUT
break
case "DELETE":
fn = s.router.DELETE
break
case "PATCH":
fn = s.router.PATCH
break
}
if fn == nil {
return
}
fn(fmt.Sprintf("/%s", desc.Name), func(ctx echo.Context) error {
vars := map[string]string{}
for _, name := range ctx.ParamNames() {
vars[name] = ctx.Param(name)
}
varsRaw, err := json.Marshal(vars)
if err != nil {
if s.logger != nil {
s.logger.Println("[dogma]", err)
}
return ctx.String(http.StatusBadRequest, "")
}
urlParam, err := typedParse[PU](varsRaw)
if err != nil {
if s.logger != nil {
s.logger.Println("[dogma]", err)
}
return ctx.String(http.StatusBadRequest, "")
}
commonParam := new(PC)
if desc.Method == http.MethodPost {
commonParam := new(PC)
err := (&echo.DefaultBinder{}).BindBody(ctx, commonParam)
if err != nil {
if s.logger != nil {
s.logger.Println("[dogma]", err)
}
return ctx.String(http.StatusBadRequest, "")
}
}
ret, err := handle(ctx, *urlParam, *commonParam)
result := struct {
ResultBase
R
}{}
if err != nil {
result.Message = err.Error()
} else {
result.R = ret
}
return ctx.JSON(http.StatusOK, ret)
})
}