1 Star 0 Fork 0

naturalCloud/go-speed

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
router.go 4.00 KB
一键复制 编辑 原始数据 按行查看 历史
naturalCloud 提交于 2023-08-27 20:06 . middleware support
package go_speed
import (
"fmt"
"strings"
)
// router 路由
type router struct {
// trees 路由树
trees map[string]*node
}
// node 路由树节点
type node struct {
path string
// 子节点,静态匹配的路由
children map[string]*node
// 通配符匹配路由 /*
starChild *node
// 参数
paramChild *node
handlerFunc HandleFunc
// 中间件
middlewares []Middleware
}
// ChildOrCreate 添加子节点
func (n *node) ChildOrCreate(path string) *node {
// 创建通配符路由
if path == "*" {
if n.paramChild != nil {
panic(fmt.Sprintf("web: 非法路由,已有路径参数路由。不允许同时注册通配符路由和参数路由 [%s]", path))
}
if n.starChild == nil {
n.starChild = &node{path: path}
}
return n.starChild
}
// 以:开头,参数路由
if path[0] == ':' {
if n.starChild != nil {
panic(fmt.Sprintf("web: 非法路由,已有路径参数路由。不允许同时注册通配符路由和参数路由 [%s]", path))
}
if n.paramChild != nil {
if n.paramChild.path != path {
panic(fmt.Sprintf("web: 路由冲突,参数路由冲突,已有 %s,新注册 %s", n.paramChild.path, path))
}
} else {
n.paramChild = &node{path: path}
}
return n.paramChild
}
if n.children == nil {
n.children = make(map[string]*node)
}
child, ok := n.children[path]
if !ok {
child = &node{path: path}
n.children[path] = child
}
return child
}
// ChildOf
func (n *node) ChildOf(path string) (*node, bool, bool) {
if n.children == nil {
if n.paramChild != nil {
return n.paramChild, true, true
}
return n.starChild, false, n.starChild != nil
}
node, found := n.children[path]
if !found {
if n.paramChild != nil {
return n.paramChild, true, true
}
return n.starChild, false, n.starChild != nil
}
return node, false, found
}
// NewRouter new
func NewRouter() *router {
return &router{trees: map[string]*node{}}
}
// AddRoute 添加路由
// 注册 path ,要排除 "",第一个不是 以 / 开头,末尾不能是 / ,中间 多个 / 的情况,在
// 在这几种情况之中,就 终止掉路由注册
func (r *router) AddRoute(method string, path string, hf HandleFunc, middlewares ...Middleware) {
// 路由不为空
if path == "" {
panic("route: 路由不能是空字符串")
}
// 路由第一个字符不是 /
if path[0] != '/' {
panic("route: 路由必须以/开头")
}
// 不是/路由情况下, 不能 / 结尾
if path != "/" && path[len(path)-1] == '/' {
panic("route: 路由不能以 / 结尾")
}
// 创建 root 节点
root, ok := r.trees[method]
if !ok {
root = &node{path: "/"}
r.trees[method] = root
}
if path == "/" {
if root.handlerFunc != nil {
panic("route: 路由冲突[/]")
}
root.handlerFunc = hf
root.middlewares = middlewares
return
}
path = path[1:]
seg := strings.Split(path, "/")
for _, s := range seg {
// 对 path中间使用连续 //abc 这种进行限制
if s == "" {
panic("route: 路由path非法,禁止使用 [//abc]..")
}
children := root.ChildOrCreate(s)
root = children
}
root.handlerFunc = hf
// 添加中间件
root.middlewares = middlewares
}
// 超找路由
func (r *router) findRoute(path string, method string) (*matchInfo, bool) {
root, ok := r.trees[method]
if !ok {
return nil, false
}
if path == "/" {
return &matchInfo{node: root, middlewares: root.middlewares}, true
}
path = strings.Trim(path, "/")
segs := strings.Split(path, "/")
mi := &matchInfo{}
for _, seg := range segs {
children, paramChild, found := root.ChildOf(seg)
if !found {
return nil, false
}
// 命中路由参数
if paramChild {
// path 是 :id 这种形式
mi.addValue(children.path[1:], seg)
}
root = children
}
mi.node = root
mi.middlewares = root.middlewares // todo
return mi, true
}
// 匹配到的路由
type matchInfo struct {
node *node
pathParam map[string]string
middlewares []Middleware
}
func (m *matchInfo) addValue(key, value string) {
if m.pathParam == nil {
m.pathParam = make(map[string]string)
}
m.pathParam[key] = value
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/naturalcloud/go-web.git
git@gitee.com:naturalcloud/go-web.git
naturalcloud
go-web
go-speed
master

搜索帮助