-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroute.go
88 lines (74 loc) · 1.69 KB
/
route.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
package chain
import (
"log/slog"
)
const (
separator = '/'
parameter = ':'
wildcard = '*'
)
type RouteConfigurator interface {
Configure(router *Router, path string)
}
type MiddlewareHandler interface {
Handle(ctx *Context, next func() error) error
}
type MiddlewareWithInitHandler interface {
Init(method string, path string, router *Router)
Handle(ctx *Context, next func() error) error
}
type Handle func(*Context) error
type Middleware struct {
Path *RouteInfo
Handle func(ctx *Context, next func() error) error
}
// Route control of a registered route
type Route struct {
Info *RouteInfo
Handle Handle
Middlewares []*Middleware
middlewaresAdded map[*Middleware]bool
}
// Dispatch ctx into this route
func (r *Route) Dispatch(ctx *Context) error {
if len(r.Middlewares) == 0 {
return r.Handle(ctx)
}
index := 0
var next func() error
next = func() error {
if index > len(r.Middlewares)-1 {
// end of middlewares
return r.Handle(ctx)
}
middleware := r.Middlewares[index]
index++
match, names, values := middleware.Path.Match(ctx)
if match {
var nextErr error
calledNext := false
nextMid := func() error {
if calledNext {
slog.Warn(
"[chain] calling next() multiple times for route",
slog.Int("index", index),
slog.String("path", ctx.path),
)
return nextErr
}
calledNext = true
nextErr = next()
return nextErr
}
if len(names) > 0 {
// middleware expects parameterizable route
return middleware.Handle(ctx.WithParams(names, values), nextMid)
} else {
// use same context
return middleware.Handle(ctx, nextMid)
}
}
return next()
}
return next()
}