forked from gin-gonic/gin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
routergroup.go
212 lines (183 loc) · 7.37 KB
/
routergroup.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
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package gin
import (
"net/http"
"path"
"regexp"
"strings"
)
type IRouter interface {
IRoutes
Group(string, ...HandlerFunc) *RouterGroup
}
type IRoutes interface {
Use(...HandlerFunc) IRoutes
Handle(string, string, ...HandlerFunc) IRoutes
Any(string, ...HandlerFunc) IRoutes
GET(string, ...HandlerFunc) IRoutes
POST(string, ...HandlerFunc) IRoutes
DELETE(string, ...HandlerFunc) IRoutes
PATCH(string, ...HandlerFunc) IRoutes
PUT(string, ...HandlerFunc) IRoutes
OPTIONS(string, ...HandlerFunc) IRoutes
HEAD(string, ...HandlerFunc) IRoutes
StaticFile(string, string) IRoutes
Static(string, string) IRoutes
StaticFS(string, http.FileSystem) IRoutes
}
// RouterGroup在内部用于配置路由器,一个RouterGroup与一个前缀相关联
//以及一系列的处理程序 (middleware).
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
var _ IRouter = &RouterGroup{}
// 使用添加中间件到组,在github中查看示例代码。.
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
group.Handlers = append(group.Handlers, middleware...)
return group.returnObj()
}
//组创建一个新的路由器组。您应该添加所有具有普通中等或相同路径前缀的路由。
//例如,所有使用公共的中间软件的路由都可以被分组。
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
return &RouterGroup{
Handlers: group.combineHandlers(handlers),
basePath: group.calculateAbsolutePath(relativePath),
engine: group.engine,
}
}
func (group *RouterGroup) BasePath() string {
return group.basePath
}
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
absolutePath := group.calculateAbsolutePath(relativePath)
handlers = group.combineHandlers(handlers)
group.engine.addRoute(httpMethod, absolutePath, handlers)
return group.returnObj()
}
//Handle用给定的路径和方法注册一个新的请求Handle和中间件。
//最后一个处理程序应该是实际的处理程序,其他的处理程序应该是可以并且应该在不同的路由之间共享的中间件。
//在github上查看示例代码。
/ /
//用于GET、POST、PUT、PATCH和DELETE请求的相应的快捷方式
//函数可以使用。
//这个函数是用于批量加载的,并且允许使用更少的
//经常使用、非标准化的或自定义的方法(例如内部的
//与代理通信)。
func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
if matches, err := regexp.MatchString("^[A-Z]+$", httpMethod); !matches || err != nil {
panic("http method " + httpMethod + " is not valid")
}
return group.handle(httpMethod, relativePath, handlers)
}
// POST 是 router.Handle("POST", path, handle)快捷方式.
func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("POST", relativePath, handlers)
}
// GET 是 router.Handle("GET", path, handle) 快捷方式.
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("GET", relativePath, handlers)
}
// DELETE 是 router.Handle("DELETE", path, handle) 快捷方式.
func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("DELETE", relativePath, handlers)
}
// PATCH 是 router.Handle("PATCH", path, handle) 快捷方式.
func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("PATCH", relativePath, handlers)
}
// PUT 是 router.Handle("PUT", path, handle) 快捷方式.
func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("PUT", relativePath, handlers)
}
// OPTIONS 是 router.Handle("OPTIONS", path, handle) 快捷方式.
func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("OPTIONS", relativePath, handlers)
}
// HEAD 是 router.Handle("HEAD", path, handle) 快捷方式.
func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("HEAD", relativePath, handlers)
}
// Any 匹配所有的 HTTP methods.
// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes {
group.handle("GET", relativePath, handlers)
group.handle("POST", relativePath, handlers)
group.handle("PUT", relativePath, handlers)
group.handle("PATCH", relativePath, handlers)
group.handle("HEAD", relativePath, handlers)
group.handle("OPTIONS", relativePath, handlers)
group.handle("DELETE", relativePath, handlers)
group.handle("CONNECT", relativePath, handlers)
group.handle("TRACE", relativePath, handlers)
return group.returnObj()
}
//StaticFile注册一条路径,以便为本地文件系统的单个文件服务。
// router.StaticFile("favicon.ico", "./resources/favicon.ico")
func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes {
if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static file")
}
handler := func(c *Context) {
c.File(filepath)
}
group.GET(relativePath, handler)
group.HEAD(relativePath, handler)
return group.returnObj()
}
//静态服务来自给定文件系统根的文件。
// 内部http.FileServer被使用, 否则 使用http.NotFound
// Router's NotFound handler.
// 使用操作系统的文件系统实现,
// 用法 :
// router.Static("/static", "/var/www")
func (group *RouterGroup) Static(relativePath, root string) IRoutes {
return group.StaticFS(relativePath, Dir(root, false))
}
// StaticFS 用于就像 `Static()` 但一个自定义 `http.FileSystem` 可以使用.
// Gin 默认使用: gin.Dir()
func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes {
if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") {
panic("URL parameters can not be used when serving a static folder")
}
handler := group.createStaticHandler(relativePath, fs)
urlPattern := path.Join(relativePath, "/*filepath")
// Register GET and HEAD handlers
group.GET(urlPattern, handler)
group.HEAD(urlPattern, handler)
return group.returnObj()
}
func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc {
absolutePath := group.calculateAbsolutePath(relativePath)
fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
_, nolisting := fs.(*onlyfilesFS)
return func(c *Context) {
if nolisting {
c.Writer.WriteHeader(404)
}
fileServer.ServeHTTP(c.Writer, c.Request)
}
}
func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain {
finalSize := len(group.Handlers) + len(handlers)
if finalSize >= int(abortIndex) {
panic("too many handlers")
}
mergedHandlers := make(HandlersChain, finalSize)
copy(mergedHandlers, group.Handlers)
copy(mergedHandlers[len(group.Handlers):], handlers)
return mergedHandlers
}
func (group *RouterGroup) calculateAbsolutePath(relativePath string) string {
return joinPaths(group.basePath, relativePath)
}
func (group *RouterGroup) returnObj() IRoutes {
if group.root {
return group.engine
}
return group
}