-
Notifications
You must be signed in to change notification settings - Fork 0
/
rider.go
392 lines (334 loc) · 10.9 KB
/
rider.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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
/*
* 路由为内部主要模块,不提供对用实现接口,请遵照一下要求:
* 1: 路由同名者,同HTTP路由重复注册,会在注册时panic;
* 2: 同名路由存在ANY以外的方法时,会选择客户端请求的方法作为响应,当没有其他方法,会响应ANY方法
* 3: 多层级子路由注册时,必须保持子路由的HTTP方法和父级路由的关系为(1:相同; 2:其中一个或两个为ANY)否者panic
* 4: 中间件注册统一为路由实例的AddMiddleware方法(中间分为根路由中间件,子路由中间件,和路由内部中间件),详情参阅example的middleware模块
5: 调用下一个中间件为context.Next(),不调用将不会继续往下执行。
* 6: 服务启动入口为rider.Listen(port:":8000");默认端口":8000";
* 7: 所有的路由都是维护在一个初始化的变量内部registeredRouters;
* 8: 支持无限极子路由,会一层一层的检测,当前层是否会有1,2情况的发生。如有1,2的情况发生,请注意错误,不会定位到完整路由。
*/
package rider // import "github.com/hypwxm/rider"
import (
ctxt "context"
"fmt"
"html/template"
"net/http"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/hypwxm/rider/logger"
"github.com/hypwxm/rider/utils/file"
)
var (
addr = ":8000"
readTimeout = 10 * time.Second
writerTimeout = 60 * time.Second
maxHeaderBytes = 1 << 20 //1MB
defaultMultipartBodySze int64 = 32 << 20
ENV_Production = "production"
ENV_Development = "development"
ENV_Debug = "debug"
)
//默认的执行的系统的环境,生产者环境
var GlobalENV = ENV_Production
type baseRider interface {
Listen(port string) //:5000 服务启动入口
registerRiderRouter(method string, path string, router *Router)
ANY(path string, router *Router)
GET(path string, router *Router)
POST(path string, router *Router)
HEAD(path string, router *Router)
OPTIONS(path string, router *Router)
DELETE(path string, router *Router)
PUT(path string, router *Router)
PATCH(path string, router *Router)
TRACE(path string, router *Router)
CONNECT(path string, router *Router)
GetServer() *HttpServer //获取
AddMiddleware(handlers ...HandlerFunc)
Error(errorHandle func(c *Context, err string, code int))
}
//http服务的入口,用户初始化和缓存服务的一些信息
type Rider struct {
server *HttpServer //注册服务用的serveMu,全局统一
routers *Router
appServer *http.Server
}
//设置环境
func SetEnvMode(mode string) {
if mode == "production" {
GlobalENV = ENV_Production
} else if mode == "development" {
GlobalENV = ENV_Development
} else if mode == "debug" {
GlobalENV = ENV_Debug
}
}
func SetEnvProduction() {
SetEnvMode("production")
}
func SetEnvDevelopment() {
SetEnvMode("development")
}
func SetEnvDebug() {
SetEnvMode("debug")
}
//初始化服务入口组建
func New() *Rider {
server := newHttpServer()
app := &Rider{
server: server,
routers: newRootRouter(server),
}
http.Handle("/", app.routers)
app.appServer = &http.Server{Handler: http.DefaultServeMux}
//默认日志等级3 warnLevel
//日志会默认初始化,调用app.Logger(int)可以改变日志的输出等级
app.server.logger = logger.NewLogger()
app.server.logger.SetLevel(3)
return app
}
func newRootRouter(server *HttpServer) *Router {
_router := NewRouter()
_router.isRoot = true
_router.fullPath = "/"
_router.Method = "ANY"
_router.SetServer(server)
return _router
}
//提供端口监听服务,监听rider里面的serveMux,调用http自带的服务启用方法
func (r *Rider) Listen(port string) (err error) {
if port == "" {
port = addr
}
r.registerTemp() // 使模板生效
r.appServer.Addr = port
r.appServer.ReadTimeout = readTimeout
r.appServer.WriteTimeout = writerTimeout
r.appServer.MaxHeaderBytes = maxHeaderBytes
fmt.Printf("The service has been started on port %v \n", port)
err = r.appServer.ListenAndServe()
if err != nil {
r.server.logger.ERROR(err.Error())
}
return
}
func (r *Rider) Graceful(port string) {
ch := make(chan os.Signal)
var err error
go func() {
err = r.Listen(port)
if err != nil {
ch <- syscall.SIGINT
}
}()
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch
r.appServer.Shutdown(ctxt.Background())
time.Sleep(300 * time.Microsecond)
}
func (r *Rider) Routers() *Router {
return r.routers
}
func (r *Rider) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
//http请求的方法的入口(ANY, GET, POST...VIA)
//path:一个跟路径,函数内部根据这个根路径创建一个根路由routers,用来管理router子路由
//router:这个根路径对应的子路由入口。
func (r *Rider) addRiderRouter(method string, path string, handlers ...HandlerFunc) {
//将app的中间处理函数传给routers根路由(后面再由routers传给其各个子路由)
//r.routers.FrontMiddleware(r.Middleware...)
//将服务注入这个组建根路由,确保路由是创立在这个服务上
//r.routers.SetServer(r.server)
//将服务注入这个组建子路由,确保路由是创立在这个服务上
//router.SetServer(r.server)
//服务注册入口内部的入口
switch method {
case "ANY":
r.routers.ANY(path, handlers...)
case "GET":
r.routers.GET(path, handlers...)
case "POST":
r.routers.POST(path, handlers...)
case "HEAD":
r.routers.HEAD(path, handlers...)
case "DELETE":
r.routers.DELETE(path, handlers...)
case "PUT":
r.routers.PUT(path, handlers...)
case "PATCH":
r.routers.PATCH(path, handlers...)
case "OPTIONS":
r.routers.OPTIONS(path, handlers...)
case "CONNECT":
r.routers.CONNECT(path, handlers...)
case "TRACE":
r.routers.TRACE(path, handlers...)
}
}
//router:这个根路径对应的子路由入口。
func (r *Rider) addChildRouter(path string, router ...IsRouterHandler) {
if len(router) == 0 {
r.server.logger.FATAL("nothing todo with no handler router")
}
for k, _ := range router {
if k < len(router)-1 {
if _, ok := router[k].(HandlerFunc); !ok {
r.server.logger.FATAL("put kid router at the end when register kid router")
}
} else {
if route, ok := router[k].(*Router); !ok {
r.server.logger.FATAL("if you want register handler directly do not use kid")
} else {
//将服务注入这个组建子路由,确保路由是创立在这个服务上
route.SetServer(r.server)
}
}
}
//服务注册入口内部的入口
r.routers.Kid(path, router...)
}
func (r *Rider) Kid(path string, middleware ...IsRouterHandler) {
r.addChildRouter(path, middleware...)
}
func (r *Rider) ANY(path string, handlers ...HandlerFunc) {
r.addRiderRouter("ANY", path, handlers...)
}
func (r *Rider) GET(path string, handlers ...HandlerFunc) {
r.addRiderRouter("GET", path, handlers...)
}
func (r *Rider) POST(path string, handlers ...HandlerFunc) {
r.addRiderRouter("POST", path, handlers...)
}
func (r *Rider) HEAD(path string, handlers ...HandlerFunc) {
r.addRiderRouter("HEAD", path, handlers...)
}
func (r *Rider) OPTIONS(path string, handlers ...HandlerFunc) {
r.addRiderRouter("OPTIONS", path, handlers...)
}
func (r *Rider) DELETE(path string, handlers ...HandlerFunc) {
r.addRiderRouter("DELETE", path, handlers...)
}
func (r *Rider) PUT(path string, handlers ...HandlerFunc) {
r.addRiderRouter("PUT", path, handlers...)
}
func (r *Rider) PATCH(path string, handlers ...HandlerFunc) {
r.addRiderRouter("PATCH", path, handlers...)
}
func (r *Rider) TRACE(path string, handlers ...HandlerFunc) {
r.addRiderRouter("TRACE", path, handlers...)
}
func (r *Rider) CONNECT(path string, handlers ...HandlerFunc) {
r.addRiderRouter("CONNECT", path, handlers...)
}
//返回服务内部的http服务入口
func (r *Rider) GetServer() *HttpServer {
return r.server
}
// 返回http.Server供自定义
func (r *Rider) GetHttpServer() *http.Server {
return r.appServer
}
//为app服务添加中间处理
func (r *Rider) USE(handlers ...HandlerFunc) {
r.routers.Middleware = append(r.routers.Middleware, handlers...)
}
//重写错误处理
func (r *Rider) Error(errorHandle func(c Context, err string, code int)) {
ErrorHandle = errorHandle
}
//设置模板路径(默认不缓存)
//tplDir以"/"开头,不会对其进行操作。如果直接以路径开头的,前面会默认跟上当前工作路径
// 调用该方法,默认启用模版
func (r *Rider) SetViews(tplDir string, extName string, funcMap template.FuncMap) {
if !(strings.HasPrefix(tplDir, "/")) {
tplDir = filepath.Join(file.GetCWD(), tplDir)
}
r.GetServer().tplDir = tplDir
r.GetServer().tplExtName = extName
r.GetServer().funcMap = funcMap
r.GetServer().openRender = true
}
// 将模板注册到服务中
func (r *Rider) registerTemp() {
if !(r.GetServer().openRender) {
return
}
if tplsRender, ok := r.GetServer().tplsRender.(*render); ok {
tplsRender.registerTpl(r.GetServer().tplDir, r.GetServer().tplExtName, r.GetServer().funcMap, "")
} else {
r.GetLogger().ERROR("模板注册失败")
}
}
//设置模板接口 (实现BaseRender接口的Render方法)
//须在SetViews方法之前调用
func (r *Rider) ViewEngine(render BaseRender) {
r.GetServer().tplsRender = render
}
//设置静态文件目录
// staticPath为文件在服务器的实际未知
// prefix,指客户端请求时的虚拟路径
func (r *Rider) SetStatic(staticPath string, prefix string) {
staticPath = strings.Replace(staticPath, "\\", "/", -1)
if !file.IsExist(staticPath) {
err := os.MkdirAll(staticPath, os.ModePerm)
if err != nil {
r.server.logger.FATAL(err.Error())
return
}
}
f, err := os.Stat(staticPath)
if err != nil {
r.server.logger.FATAL(err.Error())
return
}
if !f.IsDir() {
r.server.logger.FATAL(staticPath + "不是路径,静态文件路径必须为目录")
return
}
if strings.TrimSpace(prefix) == "" {
prefix = "/assets"
}
r.GET(prefix+"/(.*)", func(c Context) {
c.SendFile(filepath.Join(staticPath, c.PathParams()[0]))
})
}
//引入日志模块
func (r *Rider) Logger(level int) *logger.LogQueue {
//r.server.logger = logger.NewLogger()
r.server.logger.SetLevel(level)
return r.server.logger
}
//获取日志
func (r *Rider) GetLogger() *logger.LogQueue {
return r.server.logger
}
// 设置跨域信息
func (r *Rider) SetAccessCtl(access func(c Context) *AccessControl) {
r.server.accessControl = access
}
// 请求处理完成,自定义事件(比如自定义日志打印,自定义日志库)
func (r *Rider) AfterHttpResponse(ahf func(Context, int, time.Duration)) {
afterHttpResponse = ahf
}
// 获取路由信息
func (r *Rider) GetRoutes() *Router {
return r.routers
}
func (r *Rider) SetHttpReadTimeout(d time.Duration) {
readTimeout = d
}
func (r *Rider) SetHttpWriteTimeout(d time.Duration) {
writerTimeout = d
}
func (r *Rider) SetHttpMaxHeaderBytes(d int) {
maxHeaderBytes = d
}
func (r *Rider) SetHttpMaxDefaultMultipartBodySze(d int64) {
defaultMultipartBodySze = d
}