2 Star 1 Fork 1

mosache / YFrame

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
router.go 3.48 KB
一键复制 编辑 原始数据 按行查看 历史
ヤ沒脩袮兲︶ 提交于 2023-05-28 22:28 . add Y version command
package rest
import (
"fmt"
"regexp/syntax"
"strings"
)
type router struct {
trees map[string]*node
}
type node struct {
path string
//children []*node
/// static node
children map[string]*node
/// wild node 通用匹配。。只有一个
startChild *node
/// 路径参数
parmaChild *node
/// 正则参数
regChild *node
/// 正则表达式
regExpr syntax.Regexp
handler HandleFunc
}
func (n *node) childOrCreate(path string) *node {
if n.children == nil {
n.children = make(map[string]*node)
}
var (
res *node
ok bool
)
if path == "*" {
res, ok = n.startChild, n.startChild != nil
} else if strings.HasPrefix(path, ":") { // 路径参数
res, ok = n.parmaChild, n.parmaChild != nil
} else {
res, ok = n.children[path]
}
if !ok {
res = &node{path: path}
if path == "*" {
if n.parmaChild != nil {
panic(fmt.Sprintf("路径[%s]已有参数路由", n.path))
}
n.startChild = res
} else if strings.HasPrefix(path, ":") {
if n.startChild != nil && n.startChild.handler != nil {
panic(fmt.Sprintf("路径[%s]已有通配符路由", n.path))
}
n.parmaChild = res
} else {
n.children[path] = res
}
}
return res
}
/*
childOf
第一个返回值为node
第二个返回值为是否是路径参数
第三个返回值为是否匹配到
*/
func (n *node) childOf(path string) (*node, bool, bool) {
if path == "/" {
return n, false, true
}
path = strings.Trim(path, "/")
segs := strings.Split(path, "/")
var (
child = n
)
for _, seg := range segs {
var (
r *node
ok bool
)
r, ok = child.children[seg]
if !ok {
if child.parmaChild != nil {
return child.parmaChild, true, true
}
r, ok = child.startChild, child.startChild != nil
}
if !ok {
return nil, false, false
}
child = r
}
return child, false, true
}
func newRouter() *router {
return &router{trees: make(map[string]*node)}
}
func (r *router) addRoute(method string, path string, handleFunc HandleFunc) {
if path == "" {
panic("rest : path can not be nil")
}
if !strings.HasPrefix(path, "/") {
panic("rest : path must start with /")
}
if path != "/" && strings.HasSuffix(path, "/") {
panic("rest : path cannot be end with /")
}
if strings.Contains(path, "//") {
panic("rest : path cannot contain //")
}
root, ok := r.trees[method]
if !ok {
root = &node{
path: "/",
}
r.trees[method] = root
}
path = path[1:]
paths := strings.Split(path, "/")
for _, e := range paths {
if len(e) == 0 {
continue
}
child := root.childOrCreate(e)
root = child
}
if root.handler != nil {
panic(fmt.Sprintf("rest:路由冲突:[%s]重复注册", root.path))
}
root.handler = handleFunc
}
func (r *router) findRoute(method string, path string) (*matchInfo, bool) {
root, ok := r.trees[method]
if !ok {
return nil, false
}
if path == "/" {
return &matchInfo{
n: root,
params: nil,
}, true
}
path = strings.Trim(path, "/")
segs := strings.Split(path, "/")
params := make(map[string]string)
for _, seg := range segs {
n, isParamsRoute, ok := root.childOf(seg)
if !ok {
return nil, false
}
if isParamsRoute {
params[n.path[1:]] = seg
}
root = n
}
//n, isParamsRoute, ok := root.childOf(path)
//if !ok {
// return nil, false
//}
//
//if isParamsRoute {
// return &matchInfo{
// n: n,
// params: map[string]string{},
// }, true
//}
return &matchInfo{
n: root,
params: params,
}, true
}
type matchInfo struct {
n *node
params map[string]string
}
Go
1
https://gitee.com/mosache/YFrame.git
git@gitee.com:mosache/YFrame.git
mosache
YFrame
YFrame
v0.1.76

搜索帮助