-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIMiddleware.go
296 lines (252 loc) · 7.1 KB
/
IMiddleware.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
package fw
import (
"github.com/linxlib/config"
"github.com/linxlib/fw/attribute"
"net/url"
"reflect"
"strings"
)
type AttributeName = string
type SlotType = string
// MiddlewareContext represents the context in which a middleware is executed.
type MiddlewareContext struct {
ControllerName string
MethodName string
Location SlotType
param map[SlotType]string
rValue map[SlotType]reflect.Value
paramValues url.Values
rawParams string
Ignored bool
Next HandlerFunc
}
// VisitParams calls the given function f for each key/value pair in
// middleware context's parameters.
//
// f is called with the key and value of each parameter. The value is a slice
// of strings.
func (m *MiddlewareContext) VisitParams(f func(key string, value []string)) {
// Iterate over all key/value pairs in the parameters.
for s, i := range m.paramValues {
f(s, i)
}
}
// DelParam deletes the value associated with key from middleware context's
// parameters.
func (m *MiddlewareContext) DelParam(key string) {
m.paramValues.Del(key)
}
func (m *MiddlewareContext) SetRValue(v reflect.Value) {
m.rValue[m.Location] = v
}
func (m *MiddlewareContext) GetRValue() reflect.Value {
if ss, ok := m.rValue[m.Location]; ok {
return ss
} else {
return reflect.Value{}
}
}
// GetRawParams returns the raw parameters of the middleware context.
func (m *MiddlewareContext) GetRawParams() string {
return m.rawParams
}
// newMiddlewareContext creates a new MiddlewareContext instance.
//
// ctlName is the name of the controller, methodName is the name of the method,
// location is the location of the middleware, param is the parameter string,
// and next is the next handler function in the chain.
// Returns a pointer to a MiddlewareContext instance.
func newMiddlewareContext(ctlName, methodName string, location SlotType, param string, next HandlerFunc) *MiddlewareContext {
m := &MiddlewareContext{ControllerName: ctlName, MethodName: methodName, Location: location, Next: next}
m.param = make(map[SlotType]string)
m.rValue = make(map[SlotType]reflect.Value)
m.param[location] = param
m.rawParams = strings.TrimSpace(param)
var err error
m.paramValues, err = url.ParseQuery(param)
if err != nil {
m.paramValues = make(url.Values)
}
return m
}
// GetParam returns the value associated with key from middleware context's
// parameters.
//
// If the key is present in the map, the value (string) is returned.
// If the key is not present in the map, an empty string is returned.
func (m *MiddlewareContext) GetParam(key string) string {
if ss, ok := m.paramValues[key]; ok {
return strings.Join(ss, ",")
} else {
return ""
}
}
type IMiddlewareBase interface {
// Name returns the middleware's name
Name() string
// Attribute returns the middleware's Attribute just like Websocket so that you can use it like // @Websocket
Attribute() AttributeName
// GetSlot returns slot type
GetSlot() SlotType
}
// IInitOnce is an interface that will be called only once
type IInitOnce interface {
DoInitOnce()
}
type IConfig interface {
setConfig(conf *config.Config)
setProvider(provider IProvider)
LoadConfig(key string, config any)
}
type IReg interface {
// doReg inner called by fw middleware container
doReg()
}
// IMiddleware
// interface of middleware
type IMiddleware interface {
IMiddlewareBase
IConfig
IInitOnce
IReg
IProvider
}
var _ IMiddleware = (*Middleware)(nil)
// NewMiddleware creates a new Middleware instance
func NewMiddleware(name string, slot string, attr string) *Middleware {
return &Middleware{
slot: slot,
name: name,
attr: attr,
}
}
type Middleware struct {
slot string
name string
attr string
param string
config *config.Config
provider IProvider
}
func (m *Middleware) Provide(i interface{}) error {
return m.provider.Provide(i)
}
// LoadConfig loads the configuration with the specified key and value into the Middleware's config.
//
// Parameters:
// - key: the key used to identify the configuration.
// - config: the configuration value to be loaded.
//
// Return type: None.
func (m *Middleware) LoadConfig(key string, config any) {
_ = m.config.LoadWithKey(key, config)
}
func (m *Middleware) setConfig(conf *config.Config) {
m.config = conf
}
func (m *Middleware) setProvider(provider IProvider) {
m.provider = provider
}
func (m *Middleware) DoInitOnce() {
}
func (m *Middleware) doReg() {
switch m.slot {
case SlotMethod:
attribute.RegAttributeType(m.attr, attribute.TypeMiddleware)
case SlotController:
attribute.RegAttributeType(m.attr, attribute.TypeMiddleware)
case SlotGlobal:
default:
}
}
func (m *Middleware) Name() string {
return m.name
}
func (m *Middleware) Attribute() AttributeName {
return m.attr
}
func (m *Middleware) GetSlot() SlotType {
return m.slot
}
type IMiddlewareMethod interface {
IMiddleware
Execute(ctx *MiddlewareContext) HandlerFunc
}
type IMiddlewareCtl interface {
IMiddlewareMethod
Router(ctx *MiddlewareContext) []*RouteItem
}
// RouteItem is a struct that holds information about a route
//
// a Middleware can return a []*RouteItem which will be registered to server
type RouteItem struct {
Method string // HTTP METHOD
Path string // route path
IsHide bool // if set true, this route will not show in route table
H HandlerFunc // handler for this route
Middleware IMiddlewareCtl // just refer to middleware itself
OverrideBasePath bool // override base path
}
// emptyRouteItem returns an empty []*RouteItem which won't register any route
func emptyRouteItem(m IMiddlewareCtl) []*RouteItem {
return []*RouteItem{{
Method: "",
Path: "",
IsHide: false,
H: nil,
Middleware: m,
}}
}
func NewMiddlewareMethodForCtl(name string, attr string) *MiddlewareMethod {
return &MiddlewareMethod{
Middleware: NewMiddleware(name, SlotController, attr),
}
}
func NewMiddlewareMethodForGlobal(name string) *MiddlewareMethod {
return &MiddlewareMethod{
Middleware: NewMiddleware(name, SlotGlobal, name),
}
}
func NewMiddlewareCtlForGlobal(name string) *MiddlewareCtl {
return &MiddlewareCtl{
MiddlewareMethod: NewMiddlewareMethodForGlobal(name),
}
}
func NewMiddlewareCtl(name string, attr string) *MiddlewareCtl {
return &MiddlewareCtl{
MiddlewareMethod: NewMiddlewareMethodForCtl(name, attr),
}
}
type MiddlewareCtl struct {
*MiddlewareMethod
}
func (m *MiddlewareCtl) Execute(ctx *MiddlewareContext) HandlerFunc {
return ctx.Next
}
func (m *MiddlewareCtl) Router(ctx *MiddlewareContext) []*RouteItem {
return emptyRouteItem(m)
}
func NewMiddlewareMethod(name string, attr string) *MiddlewareMethod {
return &MiddlewareMethod{
Middleware: NewMiddleware(name, SlotMethod, attr),
}
}
type MiddlewareMethod struct {
*Middleware
}
type IMiddlewareGlobal interface {
IMiddlewareCtl
}
func NewMiddlewareGlobal(name string) *MiddlewareGlobal {
return &MiddlewareGlobal{
MiddlewareCtl: NewMiddlewareCtlForGlobal(name),
}
}
type MiddlewareGlobal struct {
*MiddlewareCtl
}
const (
SlotGlobal SlotType = "global"
SlotController SlotType = "controller"
SlotMethod SlotType = "method"
)