forked from OneOfOne/gserv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen.go
139 lines (117 loc) · 5.15 KB
/
gen.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package gserv
import (
"errors"
"io"
"net/http"
)
type GroupType interface {
AddRoute(method, path string, handlers ...Handler) Route
}
func Get[CodecT Codec, Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return handleOutOnly[CodecT](g, http.MethodGet, path, handler, wrapResp)
}
func JSONGet[Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Get[JSONCodec](g, path, handler, wrapResp)
}
func MsgpGet[Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Get[MsgpCodec](g, path, handler, wrapResp)
}
func Delete[CodecT Codec, Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return handleOutOnly[CodecT](g, http.MethodDelete, path, handler, wrapResp)
}
func JSONDelete[Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Delete[JSONCodec](g, path, handler, wrapResp)
}
func MsgpDelete[Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Delete[MsgpCodec](g, path, handler, wrapResp)
}
func Post[CodecT Codec, Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return handleInOut[CodecT](g, http.MethodPost, path, handler, wrapResp)
}
func JSONPost[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Post[JSONCodec](g, path, handler, wrapResp)
}
func MsgpPost[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Post[MsgpCodec](g, path, handler, wrapResp)
}
func Put[CodecT Codec, Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return handleInOut[CodecT](g, http.MethodPut, path, handler, wrapResp)
}
func JSONPut[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Put[JSONCodec](g, path, handler, wrapResp)
}
func MsgpPut[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Put[MsgpCodec](g, path, handler, wrapResp)
}
func Patch[CodecT Codec, Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return handleInOut[CodecT](g, http.MethodPatch, path, handler, wrapResp)
}
func JSONPatch[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Patch[JSONCodec](g, path, handler, wrapResp)
}
func MsgpPatch[Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, path string, handler HandlerFn, wrapResp bool) Route {
return Patch[MsgpCodec](g, path, handler, wrapResp)
}
func handleOutOnly[CodecT Codec, Resp any, HandlerFn func(ctx *Context) (resp Resp, err error)](g GroupType, method, path string, handler HandlerFn, wrapResp bool) Route {
var c CodecT
var resp Resp
_, respBytes := any(resp).([]byte)
return g.AddRoute(method, path, func(ctx *Context) Response {
resp, err := handler(ctx)
if err != nil {
return handleError[CodecT](ctx, err, wrapResp)
}
if wrapResp {
return NewResponse[CodecT](resp)
}
if respBytes {
ctx.Write(any(resp).([]byte))
return nil
}
c.Encode(ctx, resp)
return nil
})
}
func handleInOut[CodecT Codec, Req, Resp any, HandlerFn func(ctx *Context, reqBody Req) (resp Resp, err error)](g GroupType, method, path string, handler HandlerFn, wrapResp bool) Route {
var c CodecT
var req Req
var resp Resp
_, reqBytes := any(req).([]byte)
_, respBytes := any(resp).([]byte)
return g.AddRoute(method, path, func(ctx *Context) Response {
var body Req
if reqBytes {
b, err := io.ReadAll(ctx.Req.Body)
if err != nil {
return handleError[CodecT](ctx, err, wrapResp)
}
*(any(&body).(*[]byte)) = b
} else if err := c.Decode(ctx.Req.Body, &body); err != nil && !errors.Is(err, io.EOF) {
return handleError[CodecT](ctx, err, wrapResp)
}
ctx.SetContentType(c.ContentType())
resp, err := handler(ctx, body)
if err != nil {
return handleError[CodecT](ctx, err, wrapResp)
}
if wrapResp {
return NewResponse[CodecT](resp)
}
if respBytes {
ctx.Write(any(resp).([]byte))
return nil
}
c.Encode(ctx, resp)
return nil
})
}
func handleError[C Codec](ctx *Context, e error, wrapResp bool) Response {
var c C
err := getError(e)
if wrapResp {
return NewErrorResponse[C](err.Status(), err)
}
ctx.WriteHeader(err.Status())
c.Encode(ctx, getError(err))
return nil
}