118 lines
2.0 KiB
Go
118 lines
2.0 KiB
Go
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
|
|
}
|