Router
eudore.Router主要实现路由注册、中间件注册、处理函数扩展三项功能。
Router接口定义:
type Router interface {
RouterCore
RouterMethod
}
type RouterCore interface {
HandleFunc(string, string, HandlerFuncs)
Match(string, string, *Params) HandlerFuncs
}
type RouterMethod interface {
Group(string) Router
Params() *Params
AddHandler(string, string, ...interface{}) error
AddController(...Controller) error
AddMiddleware(...interface{}) error
AddHandlerExtend(...interface{}) error
AnyFunc(string, ...interface{})
GetFunc(string, ...interface{})
PostFunc(string, ...interface{})
PutFunc(string, ...interface{})
DeleteFunc(string, ...interface{})
HeadFunc(string, ...interface{})
PatchFunc(string, ...interface{})
OptionsFunc(string, ...interface{})
}
Router
路由器接口由路由器核心接口和路由器方法接口组合而成,路由器核心接口主要复制路由的注册和匹配;路由器方法接口实现组路由、路由参数设置、控制器添加、中间件添加、处理函数扩展添加和注册路由。
RouterCore
路由器核心实现路由的注册和匹配。
HandleFunc就是注册一个方法路径下的多个请求处理者。
Match就是对应的匹配实现,根据方法路径匹配出对应的多个请求处理者,同时添加对应的Params。
RouterMethod
RouterMethod接口主要有下面方法
type RouterMethod {
Group(string) Router
Params() *Params
AddHandler(string, string, ...interface{}) error
AddController(...Controller) error
AddMiddleware(...interface{}) error
AddHandlerExtend(...interface{}) error
AnyFunc(string, ...interface{})
GetFunc(string, ...interface{})
...
}
Group
Group 方法返回一个新的组路由器。
每个Group组路由注册的参数、中间件、函数扩展都不会影响上级,但是下级会继承上级数据。
新的Router将使用旧的RouterCore和Print对象;中间件信息和路由参数从上级深拷贝一份,同时处理Group参数。
以及链式创建一个新的HandlerExtender,若HandlerExtender无法注册的类型将调用上一个Router.HandlerExtender处理。
最顶级HandlerExtender对象为defaultHandlerExtend,可以使用RegisterHandlerExtend函数和NewHandlerFuncs函数调用defaultHandlerExtend对象。
func (m *RouterStd) Group(path string) Router {
return &RouterStd{
RouterCore: m.RouterCore,
HandlerExtender: NewHandlerExtendWarp(m.HandlerExtender),
params: m.ParamsCombine(path),
Print: m.Print,
}
}
Get/SetParam
读写参数用于修改当前路由参数,在Group时path中包含的路由默认参数就会解析到新组路由中,同时在注册路由的path也可能会包含路由默认参数,最后这些参数一起注册到路由,在路由匹配命中后会设置到请求上下文中。
在GetParam方法如果键为:eudore.ParamAllKeys和eudore.ParamAllVals可以获取全部路由器参数的键值,建议使用常量不使用字符串,防止在未来为了解决命名冲突而改名常量值,同时这两个key在Context当前并不支持。
AddHandler
AddHandler 添加一个新路由, 允许添加多个请求方法使用','分开。
handler参数使用当前RouterStd的HandlerExtender.NewHandlerFuncs()方法处理,生成对应的HandlerFuncs。
当前Router无法处理,则调用group前的HandlerExtender或defaultHandlerExtend处理,全部无法处理则输出error日志。
会根据当前路由路径匹配到对齐的请求中间件并附加到请求中。
而GetFunc等添加路由的方法和AddHandler行为一样,只不过AddHandler可以传入指定方法作为路由方法。
AddController
调用控制器Inject方法传入控制器和当前路由器注册路由
func (m *RouterStd) AddController(cs ...Controller) error {
var errs Errors
for _, c := range cs {
err := c.Inject(c, m)
if err != nil {
err = fmt.Errorf(ErrFormatRouterStdRegisterAddController, err)
errs.HandleError(err)
m.PrintError(0, err)
}
}
return errs.GetError()
}
AddMiddleware
AddMiddleware 给路由器添加多个中间件函数,会使用HandlerExtender转换参数。
如果参数数量大于1且第一个参数为字符串类型,会将第一个字符串类型参数作为添加中间件的路径。
func (m *RouterStd) AddMiddleware(hs ...interface{}) error {
if len(hs) == 0 {
return nil
}
path := m.GetParam("route")
if len(hs) > 1 {
perfix, ok := hs[0].(string)
if ok {
path = perfix + path
hs = hs[1:]
}
}
handlers, err := m.newHandlerFuncs(path, hs)
if err != nil {
m.PrintError(0, err)
return err
}
m.Middlewares.Insert(path, handlers)
m.Print("RegisterMiddleware:", path, handlers)
return nil
}
AddHandlerExtend
AddHandlerExtend 方法给当前Router添加扩展函数。
如果参数数量大于1且第一个参数为字符串类型,会将第一个字符串类型参数作为添加扩展函数的路径。
func (m *RouterStd) AddHandlerExtend(hs ...interface{}) error {
if len(hs) == 0 {
return nil
}
path := m.GetParam("route")
if len(hs) > 1 {
perfix, ok := hs[0].(string)
if ok {
path = perfix + path
hs = hs[1:]
}
}
var errs Errors
for _, h := range hs {
err := m.HandlerExtender.RegisterHandlerExtend(path, h)
if err != nil {
err = fmt.Errorf(ErrFormatRouterStdRegisterAddHandlerExtend, path, err)
errs.HandleError(err)
m.PrintError(0, err)
}
}
return errs.GetError()
}
Middleware
Handler接口定义了处理Context的方法。
type (
HandlerFunc func(Context)
HandlerFuncs []HandlerFunc
)
而eudore中间件处理函数与eudore.HanderFunc相同,通过ctx的next实现中间件机制。
func (ctx *ContextBase) SetHandler(fs HandlerFuncs) {
ctx.index = -1
ctx.handler = fs
}
func (ctx *ContextBase) Next() {
ctx.index++
for ctx.index < len(ctx.handler) {
ctx.handler[ctx.index](ctx)
ctx.index++
}
}
func (ctx *ContextBase) End() {
ctx.index = 0xff
}
eudore的Middleware是一个函数,类型是eudore.HandlerFunc,可以在中间件类型使用ctx.Next来调用先后续处理函数,然后再继续执行定义的内容,ctx.End直接忽略后续处理。
ctx.Fatal默认会调用ctx.End,也是和ctx.
在ContextBase实现中,将全部请求处理者使用SetHandler
方法传递给ctx,然后调用Next
方法开始循环执行处理,End
方法将执行索引移到到结束,就结束了全部的处理。
在Next
方法中调用处理,如果处理中调用了Next方法,那么在处理中就会先将后续处理完,才会继续处理,就巧妙实现Pre和Post的Handler的调用,如果处理中没有调用Next方法,就for循环继续执行处理。
例如:
func main() {
app := eudore.NewCore()
app.AddMiddleware(func(ctx eudore.Context) {
ctx.Println("前执行")
ctx.Next()
fmt.Println("后执行")
})
}