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 }