Gin 路由和中间件调用链
GIN 使用中间件:
中间件是一个 HandlerFunc,接受多参数:
func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes {
engine.RouterGroup.Use(middleware...)
engine.rebuild404Handlers()
engine.rebuild405Handlers()
return engine
}
把中间件维护到: group.Handlers
// 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()
}
添加路由
把 path 对应的 HandlerFunc append 到尾部, 再添加到路由树节点
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()
}
访问路由
GIN 启动的时候,可以看到是调用了 net/http 包:
func (engine *Engine) Run(addr ...string) (err error) {
defer func() { debugPrintError(err) }()
trustedCIDRs, err := engine.prepareTrustedCIDRs()
if err != nil {
return err
}
engine.trustedCIDRs = trustedCIDRs
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
// 此处把 engine 实例注入, 接管 http 处理
err = http.ListenAndServe(address, engine)
return
}
再看 net/http 实际处理请求的地方:
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
if req.RequestURI == "*" && req.Method == "OPTIONS" {
handler = globalOptionsHandler{}
}
// 可以看到这里 gin 接管了请求,
handler.ServeHTTP(rw, req)
}
gin处理请求, 实际调用的 c.Next()
// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()
engine.handleHTTPRequest(c)
engine.pool.Put(c)
}
func (engine *Engine) handleHTTPRequest(c *Context) {
root := t[i].root
.....
// Find route in tree
value := root.getValue(rPath, c.params, unescape)
c.Next()
.....
}
func (c *Context) Next() {
c.index++
// 计算器循环调用
for c.index < int8(len(c.handlers)) {
c.handlers[c.index](c)
c.index++
}
}
debug 一下, 当访问 /blog/list 的时候, 在 tree 中找到的路由和对应的 handlers
本作品采用《CC 协议》,转载必须注明作者和本文链接