beego:addtree support regexp
Showing
2 changed files
with
149 additions
and
9 deletions
| ... | @@ -28,21 +28,96 @@ func NewTree() *Tree { | ... | @@ -28,21 +28,96 @@ func NewTree() *Tree { |
| 28 | // add Tree to the exist Tree | 28 | // add Tree to the exist Tree |
| 29 | // prefix should has no params | 29 | // prefix should has no params |
| 30 | func (t *Tree) AddTree(prefix string, tree *Tree) { | 30 | func (t *Tree) AddTree(prefix string, tree *Tree) { |
| 31 | t.addtree(splitPath(prefix), tree) | 31 | t.addtree(splitPath(prefix), tree, nil, "") |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | func (t *Tree) addtree(segments []string, tree *Tree) { | 34 | func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg string) { |
| 35 | if len(segments) == 0 { | 35 | if len(segments) == 0 { |
| 36 | panic("prefix should has path") | 36 | panic("prefix should has path") |
| 37 | } | 37 | } |
| 38 | if len(segments) == 1 && segments[0] != "" { | 38 | seg := segments[0] |
| 39 | t.fixrouters[segments[0]] = tree | 39 | iswild, params, regexpStr := splitSegment(seg) |
| 40 | if len(segments) == 1 && seg != "" { | ||
| 41 | if iswild { | ||
| 42 | wildcards = append(wildcards, params...) | ||
| 43 | if regexpStr != "" { | ||
| 44 | for _, w := range params { | ||
| 45 | if w == "." || w == ":" { | ||
| 46 | continue | ||
| 47 | } | ||
| 48 | regexpStr = "([^/]+)/" + regexpStr | ||
| 49 | } | ||
| 50 | } | ||
| 51 | reg = reg + regexpStr | ||
| 52 | filterTreeWithPrefix(tree, wildcards, reg) | ||
| 53 | t.wildcard = tree | ||
| 54 | } else { | ||
| 55 | filterTreeWithPrefix(tree, wildcards, reg) | ||
| 56 | t.fixrouters[seg] = tree | ||
| 57 | } | ||
| 40 | return | 58 | return |
| 41 | } | 59 | } |
| 42 | seg := segments[0] | 60 | if iswild { |
| 61 | if t.wildcard == nil { | ||
| 62 | t.wildcard = NewTree() | ||
| 63 | } | ||
| 64 | wildcards = append(wildcards) | ||
| 65 | if regexpStr != "" { | ||
| 66 | for _, w := range params { | ||
| 67 | if w == "." || w == ":" { | ||
| 68 | continue | ||
| 69 | } | ||
| 70 | regexpStr = "([^/]+)/" + regexpStr | ||
| 71 | } | ||
| 72 | } | ||
| 73 | reg = reg + regexpStr | ||
| 74 | t.wildcard.addtree(segments[1:], tree, wildcards, reg) | ||
| 75 | } else { | ||
| 43 | subTree := NewTree() | 76 | subTree := NewTree() |
| 44 | t.fixrouters[seg] = subTree | 77 | t.fixrouters[seg] = subTree |
| 45 | subTree.addtree(segments[1:], tree) | 78 | subTree.addtree(segments[1:], tree, wildcards, reg) |
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | func filterTreeWithPrefix(t *Tree, wildcards []string, reg string) { | ||
| 83 | for _, v := range t.fixrouters { | ||
| 84 | filterTreeWithPrefix(v, wildcards, reg) | ||
| 85 | } | ||
| 86 | if t.wildcard != nil { | ||
| 87 | filterTreeWithPrefix(t.wildcard, wildcards, reg) | ||
| 88 | } | ||
| 89 | if t.leaf != nil { | ||
| 90 | t.leaf.wildcards = append(wildcards, t.leaf.wildcards...) | ||
| 91 | if reg != "" { | ||
| 92 | filterCards := []string{} | ||
| 93 | for _, v := range t.leaf.wildcards { | ||
| 94 | if v == ":" || v == "." { | ||
| 95 | continue | ||
| 96 | } | ||
| 97 | filterCards = append(filterCards, v) | ||
| 98 | } | ||
| 99 | t.leaf.wildcards = filterCards | ||
| 100 | t.leaf.regexps = regexp.MustCompile("^" + reg + strings.Trim(t.leaf.regexps.String(), "^$") + "$") | ||
| 101 | } else { | ||
| 102 | if t.leaf.regexps != nil { | ||
| 103 | filterCards := []string{} | ||
| 104 | for _, v := range t.leaf.wildcards { | ||
| 105 | if v == ":" || v == "." { | ||
| 106 | continue | ||
| 107 | } | ||
| 108 | filterCards = append(filterCards, v) | ||
| 109 | } | ||
| 110 | t.leaf.wildcards = filterCards | ||
| 111 | for _, w := range wildcards { | ||
| 112 | if w == "." || w == ":" { | ||
| 113 | continue | ||
| 114 | } | ||
| 115 | reg = "([^/]+)/" + reg | ||
| 116 | } | ||
| 117 | t.leaf.regexps = regexp.MustCompile("^" + reg + strings.Trim(t.leaf.regexps.String(), "^$") + "$") | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 46 | } | 121 | } |
| 47 | 122 | ||
| 48 | // call addseg function | 123 | // call addseg function |
| ... | @@ -74,6 +149,18 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, | ... | @@ -74,6 +149,18 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, |
| 74 | if t.wildcard == nil { | 149 | if t.wildcard == nil { |
| 75 | t.wildcard = NewTree() | 150 | t.wildcard = NewTree() |
| 76 | } | 151 | } |
| 152 | if regexpStr != "" { | ||
| 153 | if reg == "" { | ||
| 154 | for _, w := range wildcards { | ||
| 155 | if w == "." || w == ":" { | ||
| 156 | continue | ||
| 157 | } | ||
| 158 | regexpStr = "([^/]+)/" + regexpStr | ||
| 159 | } | ||
| 160 | } else { | ||
| 161 | regexpStr = "/" + regexpStr | ||
| 162 | } | ||
| 163 | } | ||
| 77 | t.wildcard.addseg(segments[1:], route, append(wildcards, params...), reg+regexpStr) | 164 | t.wildcard.addseg(segments[1:], route, append(wildcards, params...), reg+regexpStr) |
| 78 | } else { | 165 | } else { |
| 79 | subTree, ok := t.fixrouters[seg] | 166 | subTree, ok := t.fixrouters[seg] |
| ... | @@ -230,12 +317,11 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string | ... | @@ -230,12 +317,11 @@ func (leaf *leafInfo) match(wildcardValues []string) (ok bool, params map[string |
| 230 | } | 317 | } |
| 231 | return true, params | 318 | return true, params |
| 232 | } | 319 | } |
| 233 | 320 | if !leaf.regexps.MatchString(path.Join(wildcardValues...)) { | |
| 234 | if !leaf.regexps.MatchString(strings.Join(wildcardValues, "")) { | ||
| 235 | return false, nil | 321 | return false, nil |
| 236 | } | 322 | } |
| 237 | params = make(map[string]string) | 323 | params = make(map[string]string) |
| 238 | matches := leaf.regexps.FindStringSubmatch(strings.Join(wildcardValues, "")) | 324 | matches := leaf.regexps.FindStringSubmatch(path.Join(wildcardValues...)) |
| 239 | for i, match := range matches[1:] { | 325 | for i, match := range matches[1:] { |
| 240 | params[leaf.wildcards[i]] = match | 326 | params[leaf.wildcards[i]] = match |
| 241 | } | 327 | } | ... | ... |
| ... | @@ -31,6 +31,9 @@ func init() { | ... | @@ -31,6 +31,9 @@ func init() { |
| 31 | routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}}) | 31 | routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}}) |
| 32 | routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}}) | 32 | routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}}) |
| 33 | routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}}) | 33 | routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}}) |
| 34 | routers = append(routers, testinfo{"/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}}) | ||
| 35 | routers = append(routers, testinfo{"/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}}) | ||
| 36 | routers = append(routers, testinfo{"/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}}) | ||
| 34 | } | 37 | } |
| 35 | 38 | ||
| 36 | func TestTreeRouters(t *testing.T) { | 39 | func TestTreeRouters(t *testing.T) { |
| ... | @@ -53,6 +56,57 @@ func TestTreeRouters(t *testing.T) { | ... | @@ -53,6 +56,57 @@ func TestTreeRouters(t *testing.T) { |
| 53 | } | 56 | } |
| 54 | } | 57 | } |
| 55 | 58 | ||
| 59 | func TestAddTree(t *testing.T) { | ||
| 60 | tr := NewTree() | ||
| 61 | tr.AddRouter("/shop/:id/account", "astaxie") | ||
| 62 | tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie") | ||
| 63 | t1 := NewTree() | ||
| 64 | t1.AddTree("/v1/zl", tr) | ||
| 65 | obj, param := t1.Match("/v1/zl/shop/123/account") | ||
| 66 | if obj == nil || obj.(string) != "astaxie" { | ||
| 67 | t.Fatal("/v1/zl/shop/:id/account can't get obj ") | ||
| 68 | } | ||
| 69 | if param == nil { | ||
| 70 | t.Fatal("get param error") | ||
| 71 | } | ||
| 72 | if param[":id"] != "123" { | ||
| 73 | t.Fatal("get :id param error") | ||
| 74 | } | ||
| 75 | obj, param = t1.Match("/v1/zl/shop/123/ttt_1_12.html") | ||
| 76 | if obj == nil || obj.(string) != "astaxie" { | ||
| 77 | t.Fatal("/v1/zl//shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") | ||
| 78 | } | ||
| 79 | if param == nil { | ||
| 80 | t.Fatal("get param error") | ||
| 81 | } | ||
| 82 | if param[":sd"] != "123" || param[":id"] != "1" || param[":page"] != "12" { | ||
| 83 | t.Fatal("get :sd :id :page param error") | ||
| 84 | } | ||
| 85 | |||
| 86 | t2 := NewTree() | ||
| 87 | t2.AddTree("/v1/:shopid", tr) | ||
| 88 | obj, param = t2.Match("/v1/zl/shop/123/account") | ||
| 89 | if obj == nil || obj.(string) != "astaxie" { | ||
| 90 | t.Fatal("/v1/:shopid/shop/:id/account can't get obj ") | ||
| 91 | } | ||
| 92 | if param == nil { | ||
| 93 | t.Fatal("get param error") | ||
| 94 | } | ||
| 95 | if param[":id"] != "123" || param[":shopid"] != "zl" { | ||
| 96 | t.Fatal("get :id :shopid param error") | ||
| 97 | } | ||
| 98 | obj, param = t2.Match("/v1/zl/shop/123/ttt_1_12.html") | ||
| 99 | if obj == nil || obj.(string) != "astaxie" { | ||
| 100 | t.Fatal("/v1/:shopid/shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ") | ||
| 101 | } | ||
| 102 | if param == nil { | ||
| 103 | t.Fatal("get :shopid param error") | ||
| 104 | } | ||
| 105 | if param[":sd"] != "123" || param[":id"] != "1" || param[":page"] != "12" || param[":shopid"] != "zl" { | ||
| 106 | t.Fatal("get :sd :id :page :shopid param error") | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 56 | func TestSplitPath(t *testing.T) { | 110 | func TestSplitPath(t *testing.T) { |
| 57 | a := splitPath("/") | 111 | a := splitPath("/") |
| 58 | if len(a) != 0 { | 112 | if len(a) != 0 { | ... | ... |
-
Please register or sign in to post a comment