github.com/sirkon/goproxy@v1.4.8/tree.go (about) 1 package goproxy 2 3 import ( 4 "strings" 5 6 "github.com/sirkon/goproxy/internal/errors" 7 ) 8 9 type nodeExtension struct { 10 path string 11 node *node 12 } 13 14 type node struct { 15 f Plugin 16 further []*nodeExtension 17 } 18 19 func (n *node) addNode(path string, f Plugin) error { 20 return n.realAdd(path, path, f) 21 } 22 23 func (n *node) getNode(path string) Plugin { 24 return n.realGet(path, path) 25 } 26 27 func (n *node) realAdd(path string, origPath string, f Plugin) error { 28 if len(path) == 0 { 29 if n.f == nil { 30 n.f = f 31 } else { 32 return errors.Newf("cannot prolong a node with given path %s as it was taken before", origPath) 33 } 34 return nil 35 } 36 37 for _, ne := range n.further { 38 switch { 39 case strings.HasPrefix(path, ne.path): 40 return ne.node.realAdd(path[len(ne.path):], origPath, f) 41 case strings.HasPrefix(ne.path, path): 42 // decompose a path 43 tail := ne.path[len(path):] 44 newNode := &node{ 45 f: f, 46 further: []*nodeExtension{ 47 { 48 path: tail, 49 node: ne.node, 50 }, 51 }, 52 } 53 ne.path = path 54 ne.node = newNode 55 return nil 56 default: 57 cp := commonPrefix(path, ne.path) 58 if len(cp) > 0 { 59 tail1 := path[len(cp):] 60 tail2 := ne.path[len(cp):] 61 newNode := &node{ 62 further: []*nodeExtension{ 63 { 64 path: tail1, 65 node: &node{ 66 f: f, 67 }, 68 }, 69 { 70 path: tail2, 71 node: ne.node, 72 }, 73 }, 74 } 75 ne.path = cp 76 ne.node = newNode 77 return nil 78 } 79 } 80 } 81 82 n.further = append(n.further, &nodeExtension{ 83 path: path, 84 node: &node{ 85 f: f, 86 }, 87 }) 88 89 return nil 90 } 91 92 func commonPrefix(p1 string, p2 string) string { 93 for i := range p1 { 94 // it is clear we will stop before the end of either strings 95 if p1[i] != p2[i] { 96 return p1[:i] 97 } 98 } 99 return "" 100 } 101 102 func (n *node) realGet(path string, origPath string) Plugin { 103 for _, ne := range n.further { 104 if strings.HasPrefix(path, ne.path) { 105 res := ne.node.realGet(path[len(ne.path):], origPath) 106 if res == nil { 107 return n.f 108 } 109 return res 110 } 111 } 112 return n.f 113 }