star/httpreverse/route.go

118 lines
2.0 KiB
Go
Raw Permalink Normal View History

package httpreverse
import "strings"
type Router struct {
Hostname string
Leaf *Leaf
leafMap map[string]*Leaf
}
type Leaf struct {
Name string
Val any
Last *Leaf
Next map[string]*Leaf
FullPath string
}
func NewRouter(hostname string) *Router {
return &Router{
Hostname: hostname,
Leaf: &Leaf{
Name: "/",
Next: make(map[string]*Leaf),
FullPath: "/",
},
leafMap: make(map[string]*Leaf),
}
}
func (r *Router) AddLeaf(path string, val any) {
if r.Leaf == nil {
r.Leaf = &Leaf{
Name: "/",
Next: make(map[string]*Leaf),
FullPath: "/",
}
}
if r.leafMap == nil {
r.leafMap = make(map[string]*Leaf)
r.leafMap["/"] = r.Leaf
}
names := strings.Split(path, "/")
leaf := r.Leaf
for _, name := range names {
if name == "" {
continue
}
if leaf.Next[name] == nil {
fullPath := leaf.FullPath + "/" + name
if leaf.FullPath == "/" {
fullPath = "/" + name
}
leaf.Next[name] = &Leaf{
Name: name,
Next: make(map[string]*Leaf),
FullPath: fullPath,
}
r.leafMap[fullPath] = leaf.Next[name]
}
leaf = leaf.Next[name]
}
leaf.Val = val
}
func (r *Router) GetLeaf(path string) *Leaf {
return r.leafMap[path]
}
func (r *Router) NearestLeaf(path string) *Leaf {
if path == "/" {
return r.Leaf
}
if leaf, ok := r.leafMap[path]; ok {
return leaf
}
parts := strings.Split(path, "/")
leaf := r.Leaf
for _, v := range parts {
if v == "" {
continue
}
if leaf.Next[v] == nil {
return leaf
}
leaf = leaf.Next[v]
}
return leaf
}
func (r *Router) NearestLeafWithVal(path string) *Leaf {
if path == "/" {
return r.Leaf
}
if leaf, ok := r.leafMap[path]; ok && leaf.Val != nil {
return leaf
}
var lastValue *Leaf
parts := strings.Split(path, "/")
leaf := r.Leaf
if leaf.Val != nil {
lastValue = leaf
}
for _, v := range parts {
if v == "" {
continue
}
if leaf.Next[v] == nil {
return lastValue
}
leaf = leaf.Next[v]
if leaf.Val != nil {
lastValue = leaf
}
}
return lastValue
}