diff --git a/namespace.go b/namespace.go index e4935ac3..8ef860b4 100644 --- a/namespace.go +++ b/namespace.go @@ -256,11 +256,12 @@ func addPrefix(t *Tree, prefix string) { if t.wildcard != nil { addPrefix(t.wildcard, prefix) } - if t.leaf != nil { - if c, ok := t.leaf.runObject.(*controllerInfo); ok { + for _, l := range t.leaves { + if c, ok := l.runObject.(*controllerInfo); ok { c.pattern = prefix + c.pattern } } + } // Namespace Condition diff --git a/router.go b/router.go index 8e145bd3..51b7eaa0 100644 --- a/router.go +++ b/router.go @@ -423,8 +423,8 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin return ok, u } } - if t.leaf != nil { - if c, ok := t.leaf.runObject.(*controllerInfo); ok { + for _, l := range t.leaves { + if c, ok := l.runObject.(*controllerInfo); ok { if c.routerType == routerTypeBeego && c.controllerType.Name() == controllName { find := false if _, ok := HTTPMETHOD[strings.ToUpper(methodName)]; ok { @@ -442,20 +442,20 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin } } if find { - if t.leaf.regexps == nil { - if len(t.leaf.wildcards) == 0 { + if l.regexps == nil { + if len(l.wildcards) == 0 { return true, url } - if len(t.leaf.wildcards) == 1 { - if v, ok := params[t.leaf.wildcards[0]]; ok { - delete(params, t.leaf.wildcards[0]) + if len(l.wildcards) == 1 { + if v, ok := params[l.wildcards[0]]; ok { + delete(params, l.wildcards[0]) return true, url + "/" + v + tourl(params) } - if t.leaf.wildcards[0] == ":splat" { + if l.wildcards[0] == ":splat" { return true, url + tourl(params) } } - if len(t.leaf.wildcards) == 3 && t.leaf.wildcards[0] == "." { + if len(l.wildcards) == 3 && l.wildcards[0] == "." { if p, ok := params[":path"]; ok { if e, isok := params[":ext"]; isok { delete(params, ":path") @@ -465,7 +465,7 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin } } canskip := false - for _, v := range t.leaf.wildcards { + for _, v := range l.wildcards { if v == ":" { canskip = true continue @@ -485,33 +485,33 @@ func (p *ControllerRegistor) geturl(t *Tree, url, controllName, methodName strin } else { var i int var startreg bool - url = url + "/" - for _, v := range t.leaf.regexps.String() { + regurl := "" + for _, v := range strings.Trim(l.regexps.String(), "^$") { if v == '(' { startreg = true continue } else if v == ')' { startreg = false - if v, ok := params[t.leaf.wildcards[i]]; ok { - url = url + v + if v, ok := params[l.wildcards[i]]; ok { + delete(params, l.wildcards[i]) + regurl = regurl + v i++ } else { break } } else if !startreg { - url = string(append([]rune(url), v)) + regurl = string(append([]rune(regurl), v)) } } - if t.leaf.regexps.MatchString(url) { - return true, url + if l.regexps.MatchString(regurl) { + return true, url + "/" + regurl + tourl(params) } } - } else { - return false, "" } } } } + return false, "" } diff --git a/router_test.go b/router_test.go index a7c2f6b2..60a16248 100644 --- a/router_test.go +++ b/router_test.go @@ -95,6 +95,22 @@ func TestUrlFor(t *testing.T) { } } +func TestUrlFor2(t *testing.T) { + handler := NewControllerRegister() + handler.Add("/v1/:v/cms_:id(.+)_:page(.+).html", &TestController{}, "*:List") + handler.Add("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", &TestController{}, "*:Param") + if handler.UrlFor("TestController.List", ":v", "za", ":id", "12", ":page", "123") != + "/v1/za/cms_12_123.html" { + Info(handler.UrlFor("TestController.List")) + t.Errorf("TestController.List must equal to /v1/za/cms_12_123.html") + } + if handler.UrlFor("TestController.Param", ":v", "za", ":id", "12", ":page", "123") != + "/v1/za_cms/ttt_12_123.html" { + Info(handler.UrlFor("TestController.Param")) + t.Errorf("TestController.List must equal to /v1/za_cms/ttt_12_123.html") + } +} + func TestUserFunc(t *testing.T) { r, _ := http.NewRequest("GET", "/api/list", nil) w := httptest.NewRecorder() diff --git a/tree.go b/tree.go index ec93c8b8..26591a8c 100644 --- a/tree.go +++ b/tree.go @@ -16,7 +16,7 @@ type Tree struct { wildcard *Tree //if set, failure to match wildcard search - leaf *leafInfo + leaves []*leafInfo } func NewTree() *Tree { @@ -86,35 +86,35 @@ func filterTreeWithPrefix(t *Tree, wildcards []string, reg string) { if t.wildcard != nil { filterTreeWithPrefix(t.wildcard, wildcards, reg) } - if t.leaf != nil { - t.leaf.wildcards = append(wildcards, t.leaf.wildcards...) + for _, l := range t.leaves { + l.wildcards = append(wildcards, l.wildcards...) if reg != "" { filterCards := []string{} - for _, v := range t.leaf.wildcards { + for _, v := range l.wildcards { if v == ":" || v == "." { continue } filterCards = append(filterCards, v) } - t.leaf.wildcards = filterCards - t.leaf.regexps = regexp.MustCompile("^" + reg + strings.Trim(t.leaf.regexps.String(), "^$") + "$") + l.wildcards = filterCards + l.regexps = regexp.MustCompile("^" + reg + strings.Trim(l.regexps.String(), "^$") + "$") } else { - if t.leaf.regexps != nil { + if l.regexps != nil { filterCards := []string{} - for _, v := range t.leaf.wildcards { + for _, v := range l.wildcards { if v == ":" || v == "." { continue } filterCards = append(filterCards, v) } - t.leaf.wildcards = filterCards + l.wildcards = filterCards for _, w := range wildcards { if w == "." || w == ":" { continue } reg = "([^/]+)/" + reg } - t.leaf.regexps = regexp.MustCompile("^" + reg + strings.Trim(t.leaf.regexps.String(), "^$") + "$") + l.regexps = regexp.MustCompile("^" + reg + strings.Trim(l.regexps.String(), "^$") + "$") } } } @@ -137,9 +137,9 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, } filterCards = append(filterCards, v) } - t.leaf = &leafInfo{runObject: route, wildcards: wildcards, regexps: regexp.MustCompile("^" + reg + "$")} + t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: wildcards, regexps: regexp.MustCompile("^" + reg + "$")}) } else { - t.leaf = &leafInfo{runObject: route, wildcards: wildcards} + t.leaves = append(t.leaves, &leafInfo{runObject: route, wildcards: wildcards}) } } else { @@ -185,15 +185,18 @@ func (t *Tree) Match(pattern string) (runObject interface{}, params map[string]s func (t *Tree) match(segments []string, wildcardValues []string) (runObject interface{}, params map[string]string) { // Handle leaf nodes: if len(segments) == 0 { - if t.leaf != nil { - if ok, pa := t.leaf.match(wildcardValues); ok { - return t.leaf.runObject, pa + for _, l := range t.leaves { + if ok, pa := l.match(wildcardValues); ok { + return l.runObject, pa } } - if t.wildcard != nil && t.wildcard.leaf != nil { - if ok, pa := t.wildcard.leaf.match(wildcardValues); ok { - return t.wildcard.leaf.runObject, pa + if t.wildcard != nil { + for _, l := range t.wildcard.leaves { + if ok, pa := l.match(wildcardValues); ok { + return l.runObject, pa + } } + } return nil, nil } @@ -222,13 +225,12 @@ func (t *Tree) match(segments []string, wildcardValues []string) (runObject inte runObject, params = t.wildcard.match(segs, append(wildcardValues, seg)) } if runObject == nil { - if t.leaf != nil { - if ok, pa := t.leaf.match(append(wildcardValues, segments...)); ok { - return t.leaf.runObject, pa + for _, l := range t.leaves { + if ok, pa := l.match(append(wildcardValues, segments...)); ok { + return l.runObject, pa } } } - return runObject, params }