gin框架 中间件 是在判断路由存在前执行还是存在后执行的研究
最近有个需求,就是发现我们的验签路由中间件会在判断路由是否存在前执行。我们期望是gin框架先自己判断路由中间件是否存在,存在了再走后面的中间件,不存在直接返回404.这样能节省一定的资源。
研究了一下gin框架的源码,
先说一下表面的研究。
当我用r.Use的方式直接注册路由的时候,会是先走验证中间件后走找路由。
当我先group再用group 去注册路由的时候,就会是先找路由再走验证中间件。
然后研究gin的use源码。
这个是gin.Default的use源码
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {engine.RouterGroup.Use(middleware...)engine.rebuild404Handlers()engine.rebuild405Handlers()return engine
}
这个是group的use源码
// Use adds middleware to the group, see example code in GitHub.
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {group.Handlers = append(group.Handlers, middleware...)return group.returnObj()
}
可以看到gin.Default的use里面其实是直接调用了group的use,然后走了rebuild404Handler和rebuild405Handlers 方法。然后从函数名上就可以看出应该是rebuild404Handler 重置了判断路由是否存在的流程运行位置。
下面是
func (engine *Engine) rebuild404Handlers() {engine.allNoRoute = engine.combineHandlers(engine.noRoute)
}
然后combineHandlers
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
}
从combineHandlers 里面的代码可以看出不来,这里其实做了一个操作就是将将原来的allNoRoute 给替换掉了。新的allNoRoute 是将当前的handle组和engine.noRoute 合并起来的一个新allNoRoute 。
所以只要你是直接使用r.Use()那么你注册的路由中间件都是在路由查询之前跑的。改也很简单,要么设置路由组,要么使用r.RouterGroup.Use()来注册路由。