写点什么

Gin 路由添加流程

作者:Z.K
  • 2022-12-06
    广东
  • 本文字数:1982 字

    阅读完需:约 7 分钟

  1. 计算 absolutePath

  2. 业务 HandlerFunc 与中间件 HandlerFunc 组合

  3. Engine methodTrees 添加路由

  • methodTrees 实际上是 methodTree 组成的森林,每个 methodTree 是一颗 HTTP 方法的树

  • Engine.addRoute

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {	assert1(path[0] == '/', "path must begin with '/'")	assert1(method != "", "HTTP method can not be empty")	assert1(len(handlers) > 0, "there must be at least one handler")
debugPrintRoute(method, path, handlers)
root := engine.trees.get(method)//是否有HTTP方法的路由树 if root == nil {//没有 构建根节点 root = new(node) root.fullPath = "/" engine.trees = append(engine.trees, methodTree{method: method, root: root}) } root.addRoute(path, handlers)
// Update maxParams if paramsCount := countParams(path); paramsCount > engine.maxParams { engine.maxParams = paramsCount }
if sectionsCount := countSections(path); sectionsCount > engine.maxSections { engine.maxSections = sectionsCount }}
复制代码
  • node.addRoute

func (n *node) addRoute(path string, handlers HandlersChain) {	fullPath := path	n.priority++
// Empty tree if len(n.path) == 0 && len(n.children) == 0 { n.insertChild(path, fullPath, handlers) n.nType = root return }
parentFullPathIndex := 0
walk: for { // Find the longest common prefix. // This also implies that the common prefix contains no ':' or '*' // since the existing key can't contain those chars. i := longestCommonPrefix(path, n.path)
// Split edge if i < len(n.path) { child := node{ path: n.path[i:], wildChild: n.wildChild, indices: n.indices, children: n.children, handlers: n.handlers, priority: n.priority - 1, fullPath: n.fullPath, }
n.children = []*node{&child} // []byte for proper unicode char conversion, see #65 n.indices = bytesconv.BytesToString([]byte{n.path[i]}) n.path = path[:i] n.handlers = nil n.wildChild = false n.fullPath = fullPath[:parentFullPathIndex+i] }
// Make new node a child of this node if i < len(path) { path = path[i:] c := path[0]
// '/' after param if n.nType == param && c == '/' && len(n.children) == 1 { parentFullPathIndex += len(n.path) n = n.children[0] n.priority++ continue walk }
// Check if a child with the next path byte exists for i, max := 0, len(n.indices); i < max; i++ { if c == n.indices[i] { parentFullPathIndex += len(n.path) i = n.incrementChildPrio(i) n = n.children[i] continue walk } }
// Otherwise insert it if c != ':' && c != '*' && n.nType != catchAll { // []byte for proper unicode char conversion, see #65 n.indices += bytesconv.BytesToString([]byte{c}) child := &node{ fullPath: fullPath, } n.addChild(child) n.incrementChildPrio(len(n.indices) - 1) n = child } else if n.wildChild { // inserting a wildcard node, need to check if it conflicts with the existing wildcard n = n.children[len(n.children)-1] n.priority++
// Check if the wildcard matches if len(path) >= len(n.path) && n.path == path[:len(n.path)] && // Adding a child to a catchAll is not possible n.nType != catchAll && // Check for longer wildcard, e.g. :name and :names (len(n.path) >= len(path) || path[len(n.path)] == '/') { continue walk }
// Wildcard conflict pathSeg := path if n.nType != catchAll { pathSeg = strings.SplitN(pathSeg, "/", 2)[0] } prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path panic("'" + pathSeg + "' in new path '" + fullPath + "' conflicts with existing wildcard '" + n.path + "' in existing prefix '" + prefix + "'") }
n.insertChild(path, fullPath, handlers) return }
// Otherwise add handle to current node if n.handlers != nil { panic("handlers are already registered for path '" + fullPath + "'") } n.handlers = handlers n.fullPath = fullPath return }}
复制代码


发布于: 刚刚阅读数: 5
用户头像

Z.K

关注

还未添加个人签名 2020-07-09 加入

还未添加个人简介

评论

发布
暂无评论
Gin路由添加流程_Z.K_InfoQ写作社区