-
Notifications
You must be signed in to change notification settings - Fork 7
/
group.go
160 lines (131 loc) · 3.86 KB
/
group.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
// SPDX-FileCopyrightText: 2014-2024 caixw
//
// SPDX-License-Identifier: MIT
// Package group 提供了针对一组路由的操作
package group
import (
"fmt"
"net/http"
"slices"
"github.com/issue9/mux/v8"
"github.com/issue9/mux/v8/internal/options"
"github.com/issue9/mux/v8/internal/tree"
"github.com/issue9/mux/v8/types"
)
type (
// GroupOf 一组路由的集合
GroupOf[T any] struct {
routers []*routerOf[T]
call mux.CallOf[T]
notFound T
methodNotAllowedBuilder,
optionsBuilder types.BuildNodeHandleOf[T]
options []options.Option
middleware []types.MiddlewareOf[T]
}
routerOf[T any] struct {
r *mux.RouterOf[T]
m Matcher
}
)
// NewOf 声明 GroupOf 对象
//
// 初始化参数与 [mux.NewRouterOf] 相同,这些参数最终也会被 [GroupOf.New] 传递给新对象。
func NewOf[T any](call mux.CallOf[T], notFound T, methodNotAllowedBuilder, optionsBuilder types.BuildNodeHandleOf[T], o ...mux.Option) *GroupOf[T] {
return &GroupOf[T]{
routers: make([]*routerOf[T], 0, 1),
call: call,
notFound: notFound,
methodNotAllowedBuilder: methodNotAllowedBuilder,
optionsBuilder: optionsBuilder,
options: o,
middleware: make([]types.MiddlewareOf[T], 0, 10),
}
}
func (g *GroupOf[T]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := types.NewContext()
defer ctx.Destroy()
for _, router := range g.routers {
if ok := router.m.Match(r, ctx); ok {
router.r.ServeContext(w, r, ctx)
return
}
ctx.Reset()
}
g.call(w, r, ctx, g.notFound)
}
// New 声明新路由
//
// 新路由会继承 [NewOf] 中指定的参数,其中的 o 可以覆盖由 [NewOf] 中指定的相关参数;
func (g *GroupOf[T]) New(name string, matcher Matcher, o ...mux.Option) *mux.RouterOf[T] {
o = g.mergeOption(o...)
r := mux.NewRouterOf(name, g.call, g.notFound, g.methodNotAllowedBuilder, g.optionsBuilder, o...)
g.Add(matcher, r)
return r
}
// 将 g.options 与 o 合并,保证 g.options 在前且不会被破坏
func (g *GroupOf[T]) mergeOption(o ...mux.Option) []mux.Option {
l1 := len(g.options)
if l1 == 0 {
return o
}
l2 := len(o)
if l2 == 0 {
return g.options
}
ret := make([]mux.Option, l1+l2)
size := copy(ret, g.options)
copy(ret[size:], o)
return ret
}
// Add 添加路由
//
// matcher 用于判断进入 r 的条件,如果为空,则表示不作判断。
// 如果有多个 matcher 都符合条件,第一个符合条件的 r 获得优胜;
func (g *GroupOf[T]) Add(matcher Matcher, r *mux.RouterOf[T]) {
if matcher == nil {
matcher = MatcherFunc(anyRouter)
}
// 重名检测
if slices.IndexFunc(g.routers, func(rr *routerOf[T]) bool { return rr.r.Name() == r.Name() }) >= 0 {
panic(fmt.Sprintf("已经存在名为 %s 的路由", r.Name()))
}
r.Use(g.middleware...)
g.routers = append(g.routers, &routerOf[T]{r: r, m: matcher})
}
// Router 返回指定名称的路由
func (g *GroupOf[T]) Router(name string) *mux.RouterOf[T] {
for _, r := range g.routers {
if r.r.Name() == name {
return r.r
}
}
return nil
}
// Use 为所有已经注册的路由添加中间件
func (g *GroupOf[T]) Use(m ...types.MiddlewareOf[T]) {
for _, r := range g.routers {
r.r.Use(m...)
}
g.notFound = tree.ApplyMiddleware(g.notFound, "", "", m...)
g.middleware = append(g.middleware, m...)
}
// Routers 返回路由列表
func (g *GroupOf[T]) Routers() []*mux.RouterOf[T] {
rs := make([]*mux.RouterOf[T], 0, len(g.routers))
for _, r := range g.routers {
rs = append(rs, r.r)
}
return rs
}
func (g *GroupOf[T]) Remove(name string) {
g.routers = slices.DeleteFunc(g.routers, func(r *routerOf[T]) bool { return r.r.Name() == name })
}
func (g *GroupOf[T]) Routes() map[string]map[string][]string {
routers := g.Routers()
routes := make(map[string]map[string][]string, len(routers))
for _, r := range routers {
routes[r.Name()] = r.Routes()
}
return routes
}